SAS中的逻辑函数,用于确定变量的特定值是否为数字?

SAS中的逻辑函数,用于确定变量的特定值是否为数字?,sas,Sas,我有一个主要是数值的变量,但是偶尔会有一个字符潜入。因此,变量作为字符存储在SAS中。我希望能够确定此字符变量中的单个值是否为数字。在知道哪些值是数字,哪些是字符后,我想创建一个新的(数字)变量,其中字符变量的数值存储为数字,字符值存储为缺失 这里有一个例子 char_var --> num_var a . 1 1 2.34 2.34 ## .

我有一个主要是数值的变量,但是偶尔会有一个字符潜入。因此,变量作为字符存储在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=.;
是.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)

mydata$type你真的不需要太担心这个问题;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程序中有这个,因为我通常不需要多条错误消息来找出问题所在。

在所有示例中使用此数据集:

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正则表达式(但不是完美的,并且不包含许多有效的数字变体,如逗号或百分比;如果数据显示它们,您可以将它们添加进来)


对于大多数情况,使用简单的输入和??可能足够了。

谢谢你的建议。我刚刚尝试了一个简单的
num\u var=input(char\u var,best32.)
。这似乎做了我想要的,但我确实得到了一堆错误。这些方法是可互换的,还是我现在使用的方法有缺陷?使用
输入
函数显然是在做同样的事情(这是一个值得学习的好函数)。而且您得到的消息并不是真正的“错误”,即使它们设置了ERROR自动变量。您看到该消息的次数由SAS
errors
选项值控制。我认为这样的信息很重要,让你知道转换发生了,但是既然在你的情况下是意料之中的,我会忽略它们。对不起,鲍伯,我必须在这个问题上不同意。SAS不应该为您自动在类型之间转换,它应该报告错误(而不是警告、错误)。使用此功能可以隐藏真正的意外错误。有多种方法可以执行此测试(例如,请参见下面Joe的解决方案)。您还可以将
input()
函数与
字符一起使用,使其隐含可能存在异常字符,然后测试结果。这将实现相同的目的,而无需使用
set errors=0
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;