我有一个包含数字标识符的变量col1-col5
的数据集。标识符有2000个可能的值。我还有2000个名为dX
的变量,其中X
是2000个不同标识符值之一。
我想循环遍历col
变量,然后将由标识符索引的相应d
变量设置为等于。
例如,假设我有观察结果:
col1 col2 col3 col4 col5 d10007 d10010 d10031 ... d10057 ...
10031 10057 . . . . . . .
我想将d10031
和d10057
设置为等于1。
这可能吗?如果数字是连续的,我会看到如何使用数组,但鉴于它们不是我看不懂怎么做。
答案 0 :(得分:2)
可以在数组中完成。在关于数据结构的强制性论战之后,我将解释。
这看起来应该是一个垂直数据结构,即col
d
个变量和多行(有一些ID将它们绑在一起)。
现在,要在您拥有的结构中执行此操作:
您需要使用VNAME
功能。这允许您将数组变量的名称作为字符串获取。您无法col1=10531
并创建语句d10531=1
,但可以查看d10531
并将其值与col1
进行比较。
这很慢,因为您需要在变量上循环两次,除非您有可靠的排序。您上面的数据确实遵循排序(即,COL1-n按顺序排列,D1-n按顺序排列,因此您可以从左向右移动而不是循环两次)。如果不是这种情况,那么您可能希望将call sortn
与COL数组一起使用,如果这是可接受的。 Dxx数组应该能够以正确的顺序定义(如果它在数据集上的顺序不正确,你可以在宏变量中构造数组语句,在那里排序变量 - 数组语句中的顺序很重要,顺序在除非您使用d:
,否则数据集不会。)
以下是从左到右结构的示例。
data want;
set have;
array cols col1-col2000;
array ds d1:; *or whatever defines d;
_citer=1;
do _diter = 1 to dim(ds) while (_citer le dim(cols)); *safety check;
if compress(vname(ds[_diter]),,'kd') = cols[_citer] then do;
ds[_diter] = 1;
_citer+1;
end;
end;
run;
迭代ds
,针对当前col
检查每一个,当找到匹配时,设置然后停止。这应该是灵活的 - 即使它有很多值,也适用于ds
的任何结构。但是,如果cols
未按值的升序排序,则 not 将起作用。如果不是,你需要设置一个内循环来检查每个cols
变量,这意味着你有[dim(ds)* dim(cols)]循环迭代而不是[dim(ds)]循环迭代最多
答案 1 :(得分:2)
另一个选择是创建整个顺序D数组,然后在最后删除'假'd变量,如下所示:
data have;
Col1 = 10;
Col2 = 35;
Col3=.;
Array Dvars {*} d1 d10 d25 d35;
run;
/* Get a list of all actual D variable /*
proc sql noprint ;
select name into :dColumnsToKeep separated by ' '
From SASHELP.VColumn
where libname="WORK" and memname = "HAVE"
AND name LIKE 'd%';
;quit;
%put &dColumnsToKeep;
data want (keep=Col: &dColumnsToKeep);
set have;
array AllDVars {*} d1-d9999; *Set d9999 to as big as needed;
array ColVars {*} Col:;
do i = 1 to Dim(ColVars);
if colvars(i) ne . Then AllDvars(Colvars(i)) = 1;
end;
run;
这可能会加快处理速度,因为它可以避免循环。虽然我不知道SAS在datastep中创建10K或100K变量的记忆方式是什么。