我有一个主要是数值的变量,但偶尔会有一个字符偷偷摸摸。因此,变量作为字符存储在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
将是一个能够为我确定这一点的函数。
感谢任何建议。
在旁注中,在R中,我会尝试(可能不正确)按如下方式编程:
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)
答案 0 :(得分:5)
将此数据集用于所有示例:
data have;
input xchar $;
datalines;
1
123
123.54
1234.43
123.1.4
124A
234.1A
1234E5
12.34E7
;;;;
run;
根据您的需要,有很多不同的处理方式。
首先,您可以让SAS为您处理; Bob提供了这样的解决方案。不过,我认为这种形式非常糟糕;虽然在他的程序中很明显你是故意这样做的,但是在更长的代码中,它并不总是显而易见的,因此它可能会混淆其他程序员和/或导致数据错误。我不允许涉及故意隐式转换的代码在没有充分理由的情况下将其投入生产。
您可以使用input语句进行转换,这是SAS处理事物的更好版本。在这种情况下,您可以轻松禁止有关无效转换的警告消息。领先?抑制转换错误;单身?是否会导致在日志中打印一行以进行无效转换,但不会比没有那么突兀?
data want_qmark;
set have;
xnum = input(xchar,??BEST12.);
run;
您可以明确检查该字段;这在很大程度上取决于您的数据。以下内容适用于简单的数字字段,但最后两个(使用科学记数法)失败,并且带有两位小数的行。
if missing(compress(xnum,'.','d')) then xnum=input(xchar,best12.);
您也可以编写自己的isnumeric函数。下面使用了一个非常健壮的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;
对于大多数用途的简单输入?可能就足够了。
答案 1 :(得分: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为你做这件事。
任何BTW,选项“errors = 0”都有点误导;它与“errors = 1”相同,表示只将第一次出现的错误消息写入日志。我在autoexec.sas程序中有这个,因为我通常不需要多个错误消息来找出错误。