2017-02-21 88 views
1

由于我想制作一个宏程序来替换多个variable'missing值,它们之前的组中没有缺失的值,在此之前我需要按顺序使用多个变量对数据集进行排序以确定每一个观察。用宏替换缺失值

我有一个测试数据集:

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; 

正如你所看到的,我需要和COUNTRYNAME COUNTRYCODE进行排序。并替换缺失值devlegalaudit。我试过一个宏,如:

`%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)` 

看起来很乏味。 我无法处理任务。由于使用排序的副变量的数量可能与“替换”变量的数量不同。我希望这个宏可以适用于不同的场合。有时使用排序的idvars的数量可能比'replace'变量的数量多。有时前者可能比后者少。

希望它能说明我的问题。谢谢。

回答

0

这样做是否会产生所需的结果?

只要&变量中定义的变量缺失,它将被它自己的滞后所替代。

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); 
+0

谢谢!我已经解决了我的问题。 – JNWong

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; 
+0

谢谢!你提供了一种新的方法,它可以帮助我处理未来的案例。 – JNWong