SAS-如何使用数组在循环中跳过某些列

时间:2018-11-05 16:25:47

标签: arrays if-statement sas

我有一个包含几个数字和字符列的数据集。大多数字符列都是简单的“是”或“否”问题,但有些不是。对于数字列,我觉得我有一个有效的解决方案。对于字符列,我尝试将其最小化,但没有成功。 我想做的,并尝试了一个循环,该循环指出 j = var4的列号时,请使用Big / Small / IU替换。这样做的想法是,由于我可以在%let语句中更改var4的变量,并且代码长度较短,因此这将使代码减少“变量依赖性”。

由于dim语句为我提供了数字或字符列的总数,所以我想有些陈述使我可以将特定变量的列放置在secound循环中。但是,我没有找到这样的声明。

到目前为止,我的代码

%let v1 = var1;
%let v2 = var2;
%let v3 = var3;
%let v4 = var4;

data have;
infile datalines delimiter = '|'; 
input surveyYear id var1 var2$ var3 var4$20. ;
datalines;
2016 |  1 |     10 |   Yes |     5 |   BIG
2016 |  2 |      6 |   YES |     8 |   Big
2016 |  3 |      8 |   YEs | 99999 |   big
2016 |  4 |      . |   yes |     5 | 99999
2017 |  5 |      6 |    No |     7 | SMALL
2017 |  6 |      5 |    Ye |     . | small
2017 |  7 |  99999 |    no |     3 | 99999
2018 |  8 |      3 | 99999 |     1 | SMall
2018 |  9 |      2 |    iu |     2 |    IU
2018 | 10 |     15 |    IU |     . |    Iu
;
run; 

data want;
set have;

    array var_num[*] _numeric_;
    do i=3 to dim(var_num);
        if var_num[i] = 99999 then var_num[i] = .;
    end;

    array var_cha[*] _character_;
    do j=1 to dim(var_cha);
        var_cha(j) = upcase(var_cha(j));
        if var_cha[j]  = 'YES'     then var_cha[j] = 'Yes';
        if var_cha[j]  = 'NO'      then var_cha[j] = 'No';
        if var_cha[j]  = 'IU'      then var_cha[j] = 'IU';
        if var_cha[j]  = '99999'   then var_cha[j] = 'IU';
        if var_cha[j]  = ''        then var_cha[j] = 'IU';
    end;
/* Integrate the code below into the loop*/
    if &v4 = 'BIG'     then &v4 = 'Big city';
    if &v4 = 'SMALL'   then &v4 = 'Small city';
    if &v4 = 'IU'      then &v4 = 'Unknow city size';
    if &v4 = '99999'   then &v4 = 'Unknow city size';

drop i j;
run;

我想如何编程的概念,

data want;
set have;
array var_cha[*] _character_;
    do j=1 to dim(var_cha);
        var_cha(j) = upcase(var_cha(j));
/*      All of the if statements for the yes, no and IU */

        if var_cha[j] = ColumnNumerOfVar4 then do;
        /* where ColumnNumerOfVar4 is equal to the column number of var4*/
            if var_cha[j] =  'BIG'      then var_cha[j] = 'Big city';
            if var_cha[j] =  'SMALL'    then var_cha[j] = 'Small city';
            if var_cha[j] =  'IU'       then var_cha[j] = 'Unknow city size';
            if var_cha[j] =  '99999'    then var_cha[j] = 'Unknow city size';
        end;
    end;
run;

2 个答案:

答案 0 :(得分:2)

也许我不确定您想要的是什么,但是您似乎只是想用DO循环适用的变量名列表来创建一个宏变量,并使用它来定义数组。

%let yesnovars=var4 ;
array yesno &yesnovars;

然后您执行DO循环如下:

 do j=1 to dim(yesno);
    yesno(j) = upcase(yesno(j));
    if yesno[j]  = 'YES'     then yesno[j] = 'Yes';
    if yesno[j]  = 'NO'      then yesno[j] = 'No';
    if yesno[j]  = 'IU'      then yesno[j] = 'IU';
    if yesno[j]  = '99999'   then yesno[j] = 'IU';
    if yesno[j]  = ''        then yesno[j] = 'IU';
 end;

但实际上看起来您只想将格式应用于值。
因此,如果定义了$ YESNO格式和$ CITYSIZE格式,则可以执行以下操作将所有字符变量从原始值转换为格式化值。只需记住将它们定义足够长的时间即可容纳格式值,而不仅仅是原始值。

format var2 $yesno. var4 $citysize.;
array _c _character_;
do j=1 to dim(_c);
  _c(j)=vvalue(_c(i));
end;

甚至更好地定义INformats并在读取原始数据时使用它们。

答案 1 :(得分:1)

如果需要获取数组中变量的名称,则可以使用vName函数:

Test_Gl(ItemNo).currency_amount = new CurrencyAmount

据我了解,这可以解决您的问题。但是,如果您还想获取特定变量的列号,则可以通过查看sasHelp.vColumns并将其放入宏变量中来实现。或在数据步骤的开头执行以下操作:

    if (vName(var_cha[j]) = 'var4') then do;
    /* where ColumnNumberOfVar4 is equal to the column number of var4*/
        if var_cha[j] =  'BIG'      then var_cha[j] = 'Big city';
        if var_cha[j] =  'SMALL'    then var_cha[j] = 'Small city';
        if var_cha[j] =  'IU'       then var_cha[j] = 'Unknow city size';
        if var_cha[j] =  '99999'    then var_cha[j] = 'Unknow city size';
    end;

但是我认为这不是您需要做的事情。