我有一个带有很多缺失值的SAS表。这只是一个简单的例子。真实表更大(> 1000行(,而且数字不同。但是,我有一个没有丢失数字的列A。B列和C的序列比A。
的长度短a b c
1 1b 1000
2 2b 2000
3 3b
4
5
6
7
我想要的是用重复序列填充b和b,直到列已满。结果应该看起来像:
a b c
1 1b 1000
2 2b 2000
3 3b 1000
4 1b 2000
5 2b 1000
6 3b 2000
7 1b 1000
我试图制作一个宏,但变成了混乱。
我怀疑这是最灵活的哈希式解决方案。
。data have;
infile datalines delimiter="|";
input a b $ c;
datalines;
1|1b|1000
2|2b|2000
3|3b|
4| |
5| |
6| |
7| |
;;;;
run;
%let vars=b c;
data want;
set have;
rownum = _n_;
if _n_=1 then do;
declare hash hoh(ordered:'a');
declare hiter hih('hoh');
hoh.defineKey('varname');
hoh.defineData('varname','hh');
hoh.defineDone();
declare hash hh();
do varnum = 1 to countw("&vars.");
varname = scan("&vars",varnum);
hh = _new_ hash(ordered:'a');
hh.defineKey("rownum");
hh.defineData(varname);
hh.defineDone();
hoh.replace();
end;
end;
do rc=hih.next() by 0 while (rc=0);
if strip(vvaluex(varname)) in (" ",".") then do;
num_items = hh.num_items;
rowmod = mod(_n_-1,num_items)+1;
hh.find(key:rowmod);
end;
else do;
hh.replace();
end;
rc = hih.next();
end;
keep a &Vars.;
run;
基本上,为您使用的每个变量构建一个哈希。它们每个都添加到哈希的哈希中。然后,我们迭代这一点,然后搜索以查看是否填充了请求的变量。如果是这样,我们将其添加到它的哈希中。如果不是,我们会检索适当的一个。
假设您可以通过计算列中有多少个不弥合值来确定每个变量使用多少行,那么您可以使用此代码生成技术来生成一个数据步骤将使用点=选项集语句来循环循环通过第一个NX观测值x。
首先获取变量名的列表;
proc transpose data=have(obs=0) out=names ;
var _all_;
run;
然后使用这些生成Proc SQL Select语句来计算每个变量的非解散值的数量。
filename code temp ;
data _null_;
set names end=eof ;
file code ;
if _n_=1 then put 'create table counts as select ' ;
else put ',' @;
put 'sum(not missing(' _name_ ')) as ' _name_ ;
if eof then put 'from have;' ;
run;
proc sql noprint;
%include code /source2 ;
quit;
然后转动该转换,以便您又有一个每个变量名称的行,但是这次它也具有Col1中的计数。
proc transpose data=counts out=names ;
var _all_;
run;
现在使用它来生成数据步骤所需的设置语句,以从输入创建输出。
filename code temp;
data _null_;
set names ;
file code ;
length pvar $32 ;
pvar = cats('_point',_n_);
put pvar '=mod(_n_-1,' col1 ')+1;' ;
put 'set have(keep=' _name_ ') point=' pvar ';' ;
run;
现在使用生成的语句。
data want ;
set have(drop=_all_);
%include code / source2;
run;
因此,对于带有变量A,B和C的示例数据文件和7个总观测值,生成的数据步骤的日志如下:
1229 data want ;
1230 set have(drop=_all_);
1231 %include code / source2;
NOTE: %INCLUDE (level 1) file CODE is file .../#LN00026.
1232 +_point1 =mod(_n_-1,7 )+1;
1233 +set have(keep=a ) point=_point1 ;
1234 +_point2 =mod(_n_-1,3 )+1;
1235 +set have(keep=b ) point=_point2 ;
1236 +_point3 =mod(_n_-1,2 )+1;
1237 +set have(keep=c ) point=_point3 ;
NOTE: %INCLUDE (level 1) ending.
1238 run;
NOTE: There were 7 observations read from the data set WORK.HAVE.
NOTE: The data set WORK.WANT has 7 observations and 3 variables.
填充带有值的临时数组,然后检查行并添加适当的值。
设置数据
data have;
infile datalines delimiter="|";
input a b $ c;
datalines;
1|1b|1000
2|2b|2000
3|3b|
4| |
5| |
6| |
7| |
;
获取非零值的计数
proc sql noprint;
select count(*)
into :n_b
from have
where b ^= "";
select count(*)
into :n_c
from have
where c ^=.;
quit;
现在通过重复每个数组的内容来填充缺失值。
data want;
set have;
/*Temporary Arrays*/
array bvals[&n_b] $ 32 _temporary_;
array cvals[&n_c] _temporary_;
if _n_ <= &n_b then do;
/*Populate the b array*/
bvals[_n_] = b;
end;
else do;
/*Fill the missing values*/
b = bvals[mod(_n_+&n_b-1,&n_b)+1];
end;
if _n_ <= &n_c then do;
/*populate C values array*/
cvals[_n_] = c;
end;
else do;
/*fill in the missing C values*/
c = cvals[mod(_n_+&n_c-1,&n_c)+1];
end;
run;
data want;
set have;
n=mod(_n_,3);
if n=0 then b='3b';
else b=cats(n,'b');
if n in (1,0) then c=1000;
else c=2000;
drop n;
run;