在多个 (>50) 列上使用散列查找 table
Lookup table using hash on multiple (>50) columns
我正在使用一个包含超过 50 列的 table。我正在尝试使用查找 table.
替换多列的值
Table
:
data have;
infile datalines delimiter=",";
input ID . SUB_ID :. COUNTRY :. A . B .;
datalines;
1,A,FR,A,B
2,B,CH,,B
3,C,DE,B,A
4,D,CZ,,B
5,E,GE,A,
6,F,EN,B,
7,G,US,,A
;
run;
Lookup table
:
data lookup;
infile datalines delimiter=",";
input value_before . value_after :.;
datalines;
A,1
B,2
C,3
;
run;
Actual code
:
data want;
if 0 then set lookup;
if _n_ = 1 then do;
declare hash lookup(dataset:'lookup');
lookup.defineKey('value_before');
lookup.defineData('value_after');
lookup.defineDone();
end;
set have;
if (lookup.find(key:A) = 0) then
A = value_after;
if (lookup.find(key:B) = 0) then
B = value_after;
/* ... */
/* if (lookup.find(key:Z) = 0) then
Z = value_after; */
drop value_before value_after;
run;
我想如果我对 50 列进行硬编码,这段代码就可以完成这项工作。
我想知道是否有一种方法可以将 hash.find() “应用”到除前三个变量 (ID, SUB_ID and Country
) 之外的所有变量(也许通过索引?)而不必对它们进行硬编码或使用宏。为了举例,我只计算了 2 个变量来替换值(A 和 B),但有超过 50 个(名称完全不同,没有像 var1,var2,...,varn
这样的模式)。
在这种情况下,我喜欢使用proc sql
和字典table来填充列名,以便我创建一个数组。下面的代码将从 dictionary.columns
中提取变量名称,并将它们以 space 分隔保存到宏变量 varnames
中。我们可以将其输入一个数组,然后使用数组逻辑来完成剩下的工作。
proc sql noprint;
select name
into :varnames separated by ' '
from dictionary.columns
where libname = 'WORK'
AND memname = 'HAVE'
AND name NOT IN('ID', 'SUB_ID', 'COUNTRY')
;
quit;
data want;
if 0 then set lookup;
if _n_ = 1 then do;
declare hash lookup(dataset:'lookup');
lookup.defineKey('value_before');
lookup.defineData('value_after');
lookup.defineDone();
end;
set have;
array vars[*] &varnames.;
do i = 1 to dim(vars);
if lookup.Find(key:vars[i])=0 then vars[i] = value_after;
end;
drop value_before value_after i;
run;
我正在使用一个包含超过 50 列的 table。我正在尝试使用查找 table.
替换多列的值Table
:
data have;
infile datalines delimiter=",";
input ID . SUB_ID :. COUNTRY :. A . B .;
datalines;
1,A,FR,A,B
2,B,CH,,B
3,C,DE,B,A
4,D,CZ,,B
5,E,GE,A,
6,F,EN,B,
7,G,US,,A
;
run;
Lookup table
:
data lookup;
infile datalines delimiter=",";
input value_before . value_after :.;
datalines;
A,1
B,2
C,3
;
run;
Actual code
:
data want;
if 0 then set lookup;
if _n_ = 1 then do;
declare hash lookup(dataset:'lookup');
lookup.defineKey('value_before');
lookup.defineData('value_after');
lookup.defineDone();
end;
set have;
if (lookup.find(key:A) = 0) then
A = value_after;
if (lookup.find(key:B) = 0) then
B = value_after;
/* ... */
/* if (lookup.find(key:Z) = 0) then
Z = value_after; */
drop value_before value_after;
run;
我想如果我对 50 列进行硬编码,这段代码就可以完成这项工作。
我想知道是否有一种方法可以将 hash.find() “应用”到除前三个变量 (ID, SUB_ID and Country
) 之外的所有变量(也许通过索引?)而不必对它们进行硬编码或使用宏。为了举例,我只计算了 2 个变量来替换值(A 和 B),但有超过 50 个(名称完全不同,没有像 var1,var2,...,varn
这样的模式)。
在这种情况下,我喜欢使用proc sql
和字典table来填充列名,以便我创建一个数组。下面的代码将从 dictionary.columns
中提取变量名称,并将它们以 space 分隔保存到宏变量 varnames
中。我们可以将其输入一个数组,然后使用数组逻辑来完成剩下的工作。
proc sql noprint;
select name
into :varnames separated by ' '
from dictionary.columns
where libname = 'WORK'
AND memname = 'HAVE'
AND name NOT IN('ID', 'SUB_ID', 'COUNTRY')
;
quit;
data want;
if 0 then set lookup;
if _n_ = 1 then do;
declare hash lookup(dataset:'lookup');
lookup.defineKey('value_before');
lookup.defineData('value_after');
lookup.defineDone();
end;
set have;
array vars[*] &varnames.;
do i = 1 to dim(vars);
if lookup.Find(key:vars[i])=0 then vars[i] = value_after;
end;
drop value_before value_after i;
run;