用宏替换缺失值

时间:2017-02-21 07:52:15

标签: macros sas

由于我想制作一个宏程序,用一个组中先前的非缺失值替换多个变量'缺失值,在此之前我需要使用多个变量对数据集进行排序,以便识别每个观察结果

我有一个测试数据集:

data temp2;
input countryname $1-5 +1 countrycode $7-8 +1 dev 1. +1 legal 1. +1 audit 1.;
datalines;
china 22 9 2 3
china 22 . . 3
china 22 7 3 .
china 21 4 . .
japan 13 3 . 1
japan 12 3 . .
japan 13 1 2 3
 ;
run;

正如您所看到的,我需要按国家/地区名称和国家/地区代码进行排序。并替换dev legal audit缺失值。我尝试过像:

这样的宏
`%macro replace(dsetin=,dsetout=,idvars=,vars=);
 %if &dsetout = %then %let dsetout = &dsetin;
 %let char=_;
 %do xi=1 %to %sysfunc(countw(&vars));
 %let var = %scan(&vars,&xi);
 %let  _VARs_=%sysfunc(cat(&char,&var));
 %end;
 %let m=%sysfunc(countw(&vars));
 %do yi=1 %to %sysfunc(countw(&idvars));
 %let idvar = %scan(&idvars,&yi);
 %let lagid = lag(&idvar);
 %end;
 %let n=%sysfunc(countw(&idvars));
 proc sort data=&dsetin out=temp1;
 by &idvars;
 run;
 data &dsetout;
 set temp1;
 by &idvars;
 array id(&n)&idvar;
 array lag(&n)&lagid;
 array vara(&m)&var;
 array vars(&m)&_VARs_;
 do yi = 1 to &n;
 if lag(yi)=id(yi) then do;
 do xi= 1 to &m;
 retain &_VARs_;
 if not missing(&var) then &_VARs_ =&var;
else &var = &_VARs_; 
end;
%end;
end;
drop of &_VARs_:;
run;
%mend replace;
%replace(dsetin=temp,dsetout=temp2,idvars=countryname countrycode,vars=DEV LEGAL AUDIT)`

这似乎乏味。 我无法处理这项任务。由于使用排序的变量的数量可能与“替换”的数量不同。变量。我希望宏可以应用于不同的场合。有时,使用sort的idvars数量可能会超过“替换”的数量。变量。有时前者可能比后者少。

希望它可以说明我的问题。感谢。

2 个答案:

答案 0 :(得分:0)

这样的事情会产生预期的效果吗?

每当缺少在& vars中定义的变量时,它将被替换为它自己的滞后。

data temp;
    input countryname $1-5 +1 countrycode $7-8 +1 dev 1. +1 legal 1. +1 audit 1.;
    datalines;
china 22 9 2 3
china 22 . . 3
china 22 7 3 .
china 21 4 . .
japan 13 3 . 1
japan 12 3 . .
japan 13 1 2 3
;run;

%macro replace(dsetin,dsetout,idvars,vars);
    %if &dsetout = %then %let dsetout = &dsetin;

    proc sort data=&dsetin out=temp1;
        by &idvars;
    run;

    data &dsetout;
        set temp1;
        *by &idvars;

        array variables &vars;
        array lags {%sysfunc(countw("&vars"))};

        do i=1 to countw("&vars");
            lags[i] = lag(variables[i]);
            if variables[i]=. then variables[i] = lags[i];
        end;

        drop of lags: ;
        drop i;

    run;

%mend replace;
%replace(temp,,countryname countrycode,DEV LEGAL AUDIT);

答案 1 :(得分:0)

您可以使用UPDATE语句来转发非缺失值。

因此我们可以创建这个宏来对数据进行排序,然后使用UPDATE语句来转发所选变量的非缺失值。通过添加额外的SET语句,我们可以确保任何其他变量不受UPDATE操作的影响。最后,我们需要一个OUTPUT语句来编写每个观察,否则只会写入BY组的最后一个观察。如果将VARS留空,我们甚至可以使其足够智能以更新所有非变量。

%macro replace(dsetin=,dsetout=,idvars=,vars=);
  %if not %length(&dsetin) %then %let dsetin=&syslast;
  %if not %length(&dsetout) %then %let dsetout=&dsetin ;
  %if %length(&vars) %then %let vars=&idvars &vars;
  proc sort data=&dsetin out=&dsetout;
    by &idvars;
  run;
  data &dsetout ;
    update &dsetout (obs=0) &dsetout (keep=&vars) ;
    by &idvars ;
    set &dsetout(drop=&vars);
    output;
  run;
%mend replace ;

现在让我们构建一些测试数据:

data have;
  length countryname $5 countrycode $2 dev legal audit 8 ;
  input countryname -- audit ;
datalines;
china 22 9 2 3
china 22 . . 3
china 22 7 3 .
china 21 4 . .
japan 13 3 . 1
japan 12 3 . .
japan 13 1 2 3
;;;;

运行宏并保留所有变量。然后只有一个。

%replace(dsetin=have,dsetout=want1,idvars=countryname countrycode,vars=);
%replace(dsetin=have,dsetout=want2,idvars=countryname countrycode,vars=legal);

然后比较结果。

proc compare data=want1 compare=want2 ;
run;