【问题标题】:Logical function in SAS to determine if a particular value of a variable is numeric?SAS中的逻辑函数确定变量的特定值是否为数字?
【发布时间】:2013-06-07 21:16:29
【问题描述】:

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

【问题讨论】:

    标签: sas


    【解决方案1】:

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

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

    根据您的需要,有很多不同的处理方式。

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

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

    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;
    

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 感谢您的建议。我只是尝试了一个简单的num_var=input(char_var,best32.)。这似乎已经完成了我想要的,但我确实得到了一堆错误。这些方式是可以互换的,还是我现在使用的方式有缺陷?
      • 使用input 函数明确地做同样的事情(并且是一个很好的学习函数)。而且您收到的消息并不是真正的“错误”,即使它们确实设置了 ERROR 自动变量。您看到该消息的次数由 SAS errors 选项值控制。我认为此类消息对于让您知道发生了转换很重要,但由于您的情况是预期的,因此我会忽略它们。
      • 对不起,鲍勃,我不同意这一点。 SAS 不应该自动为您转换类型,它应该报告错误(不是警告,而是错误)。利用此功能可以隐藏真正的意外错误。 pragprog.com/the-pragmatic-programmer/extracts/coincidence 。有多种方法可以执行此测试(例如,请参阅下面 Joe 的解决方案)。您还可以使用input() 函数和? 字符来暗示可能存在异常字符,然后测试结果。这将达到相同的目的而无需使用set errrors=0
      猜你喜欢
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多