3

我有一个主要是数值的变量,但是偶尔会有一个字符潜入。因此,变量在 SAS 中存储为字符。我希望能够确定此字符变量中的各个值是否为数字。在知道哪些值是数字以及哪些是字符之后,我想创建一个新的(数字)变量,其中字符变量的数值存储为数字,而字符值存储为缺失值。

这是一个例子。

   char_var -->   num_var
    a              .
    1              1
    2.34           2.34
    ##             .
    cat            .

我希望能够做到以下几点,但我缺少一个可以帮助我的功能:

if char_var=is.numeric(char_var) then num_var=char_var;
        else num_var=.;

is.numeric将是一个为我确定这一点的函数。

任何建议表示赞赏。

附带说明一下,在 RI 中会尝试(可能不正确)按如下方式进行编程:

mydata$type<-is.numeric(mydata$char_var)
if (mydata$type==1) {mydata$num_var=mydata$char_var} else {mydata$num_var=NA}
mydata$num_var<-as.numeric(mydata$num_var)
4

2 回答 2

5

将此数据集用于所有示例:

data have;
input xchar $;
datalines;
1
123
123.54
1234.43
123.1.4
124A
234.1A
1234E5
12.34E7
;;;;
run;

有很多不同的方法来处理这个,这取决于你的需要。

首先,您可以让 SAS 为您处理;Bob 提供了这样的解决方案。不过,我认为这种形式很糟糕;虽然在他的程序中很明显你是故意这样做的,但在较长的代码中并不总是很明显,因此它可能会混淆其他程序员和/或导致数据错误。我不允许涉及故意隐式转换的代码在没有充分理由的情况下将其投入生产。

您可以使用输入语句进行转换,这是 SAS 处理事物的更好版本。在这种情况下,您可以轻松地隐藏有关无效转换的警告消息。领先??抑制转换错误;单?会导致将一行打印到日志中以进行无效转换,但比 no 更不显眼。

data want_qmark;
set have;
xnum = input(xchar,??BEST12.);
run;

您可以明确检查该字段;这在很大程度上取决于您的数据。以下将适用于简单的数字字段,但在最后两个(使用科学记数法)和带有两位小数的行上失败。

if missing(compress(xnum,'.','d'))  then xnum=input(xchar,best12.);

您也可以编写自己的非数字函数。下面使用了一个相当健壮的 perl 正则表达式(但并不完美,并且不包括许多有效的数字变体,例如逗号或百分比;如果您的数据建议它们,您可以添加它们)。

options cmplib=work.funcs;
proc fcmp outlib=work.funcs.test;
 function isnumeric(value $);
  prx = prxparse('/^-?\d+\.?\d*(e\d+)?$/io');
  rc = prxmatch(prx,trimn(value));
  return(rc);
 endsub;
 quit;

data want_fcmp;
set have;
if isnumeric(xchar) then xnum=input(xchar,BEST12.);
run;

对于大多数使用简单的输入??可能就足够了。

于 2013-06-09T05:38:45.077 回答
0

你真的不需要太担心这个;SAS 很乐意为您将变量转换为数值变量。例如:

options errors=0;
data have;
   input char_var $;
   length num_var 8; /* To make a numeric variable */
   num_var = char_var;
   put char_var=
     / num_var=;
   datalines;
a
1           
2.34    
## 
cat
run;

我最喜欢的 SAS 选项 (errors=0) 用于抑制 SAS 在转换时放入日志中的消息。如果字符值可以解释为数字,则转换将毫无问题地进行。可能有一种方法可以扫描字符变量以查看它是否会产生一个数字,但我敢打赌,这种解决方案的开销“成本”不仅仅是让 SAS 为你做这件事。

顺便说一句,选项“errors=0”有点误导;它与“errors=1”相同,意味着只有第一次出现的错误消息被写入日志。我在我的 autoexec.sas 程序中有这个,因为我通常不需要多个错误消息来找出问题所在。

于 2013-06-07T21:57:46.603 回答