Loops 查找数据集中具有特定值的列的索引

Loops 查找数据集中具有特定值的列的索引,loops,sas,Loops,Sas,我有一个表,其中行是标识符,列是标记,如下所示 ID C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 17028 0 1 0 0 0 1 0 0 1 0 17030 1 1 1 0 1 0 0 0 1 0 17037 0 1 0 0 0 0 0 1 1 0 17040 1 1 0 0 1 0 0 0 1

我有一个表,其中行是标识符,列是标记,如下所示

ID  C1  C2  C3  C4  C5  C6  C7  C8  C9  C10
17028   0   1   0   0   0   1   0   0   1   0
17030   1   1   1   0   1   0   0   0   1   0
17037   0   1   0   0   0   0   0   1   1   0
17040   1   1   0   0   1   0   0   0   1   0
17041   0   1   0   0   0   0   1   0   1   0
对于每一行,我需要一个标志,它表示值为1的变量的串联名称或索引

这是我使用的代码,但似乎有点效率,虽然可以完成工作

data temp71;
set temp7;
format flag 20.;
flag=0;
if c1= 1 then flag=flag+1000000000000000;
if c2= 1 then flag=flag+100000000000000;
if c3= 1 then flag=flag+10000000000000;
if c4= 1 then flag=flag+1000000000000;
if c5= 1 then flag=flag+100000000000;
if c6= 1 then flag=flag+10000000000;
if c7= 1 then flag=flag+1000000000;
if c8= 1 then flag=flag+100000000;
if c9= 1 then flag=flag+10000000;
if c10= 1 then flag=flag+1000000;
if c11= 1 then flag=flag+100000;
if c12= 1 then flag=flag+10000;
if c13= 1 then flag=flag+1000;
if c14= 1 then flag=flag+100;
if c15= 1 then flag=flag+10;
if c16= 1 then flag=flag+1;
run;

注意:此解决方案是在编辑之前发布的,提供的结果与您以前尝试的结果不同

data have;
  input ID $  C1  C2  C3  C4  C5  C6  C7  C8  C9  C10;
  datalines;
17028   0   1   0   0   0   1   0   0   1   0
17030   1   1   1   0   1   0   0   0   1   0
17037   0   1   0   0   0   0   0   1   1   0
17040   1   1   0   0   1   0   0   0   1   0
17041   0   1   0   0   0   0   1   0   1   0
;

data want(drop=i);
  set have;
  array C(10);
  format flag $20.;
  do i = 1 to 10;
    if C(i) = 1 then flag = catx(",",flag,put(i,1.));
  end;
run;

proc print data=want;
  var flag;
run;
结果:

Obs flag 
1   2,6,9 
2   1,2,3,5,9 
3   2,8,9 
4   1,2,5,9 
5   2,7,9 

您可以使用CAT函数将所有变量连接在一起,一行代码将生成您的标志变量

flag = catt(of c1--c10);
但是,您还指出可能需要变量的名称,因此还可以使用catx函数将这些名称连接在一起。下面是一个如何工作的示例:

data have;
input ID $  C1  C2  C3  C4  C5  C6  C7  C8  C9  C10;
cards;
17028   0   1   0   0   0   1   0   0   1   0
17030   1   1   1   0   1   0   0   0   1   0
17037   0   1   0   0   0   0   0   1   1   0
17040   1   1   0   0   1   0   0   0   1   0
17041   0   1   0   0   0   0   1   0   1   0
;
run;


data want;

set have;
array c(10) c1-c10;

flag = catt(of c1--c10);

length names $50.;

do i=1 to dim(c);
if c(i)=1 then names=catx(", ", names, vname(c(i)));
end;
run;

最好使用字符变量而不是数字。如果使用字符变量,则可以保留32767个标志

flagc = cats(of c1-c10);
如果您尝试使用基数10执行操作,则一个数字中只能包含15个标志。如果使用base 2,您可以持有53面旗帜

%let nvars=10;
data want ;
  set have ;
  length flagc $&nvars flag2 flag10 8;
  format flag2 binary&nvars.. flag10 z&nvars..;
  flagc = cats(of c1-c&nvars);
  flag10 = input(flagc,&nvars..);
  flag2  = input(flagc,binary&nvars..);
  put id (c1-c&nvars) (1.) +1 flag2 flag10 flagc ;
run;

17028 0100010010 0100010010 0100010010 0100010010
17030 1110100010 1110100010 1110100010 1110100010

@汤姆:我已经把我试过的代码包括进去了。@Reeze:很有效,谢谢。谢谢你的帮助。