假设我有两个数据集 A 和 B,它们具有相同的变量,并且希望根据 A 中的值而不是 B 本身对 B 中的值进行排名(如“PROC RANK data=B”所做的那样。)
这是数据集 A、B 和 Want(所需输出)的简化示例:
A:
obs_A VAR1 VAR2 VAR3
1 10 100 2000
2 20 300 1000
3 30 200 4000
4 40 500 3000
5 50 400 5000
B:
obs_B VAR1 VAR2 VAR3
1 15 150 2234
2 14 352 1555
3 36 251 1000
4 41 350 2011
5 60 553 5012
want:
obs VAR1 VAR2 VAR3
1 2 2 3
2 2 4 2
3 4 3 1
4 5 4 3
5 6 6 6
我想出了一个涉及 PROC RANK 和 PROC APPEND 的宏循环,如下所示:
%macro MyRank(A,B);
data AB; set &A &B; run;
%do i=1 %to 5;
proc rank data=AB(where=(obs_A ne . OR obs_B=&i) out=tmp;
var VAR1-3;
run;
proc append base=want data=tmp(where=(obs_B=&i) rename=(obs_B=obs)); run;
%end;
%mend;
当 B 中的观测值数量较少时,这是可以的。但当涉及到非常大的数字时,需要很长时间,因此这不是一个好的解决方案。
提前感谢您的建议。
最佳答案
我会创建格式来做到这一点。您真正要做的是通过 A 定义要应用于 B 的范围。格式非常快 - 这里假设“A”相对较小,“B”可以根据您的需要而大,并且总是只需要只要读取和写入 B 数据集一次,再加上 A 数据集的几次读取/写入即可。
首先,读入A数据集:
data ranking_vals;
input obs_A VAR1 VAR2 VAR3;
datalines;
1 10 100 2000
2 20 300 1000
3 30 200 4000
4 40 500 3000
5 50 400 5000
;;;;
run;
然后将其转换为垂直,因为这将是对它们进行排名的最简单方法(只是普通的旧排序,不需要过程排名)。
data for_ranking;
set ranking_vals;
array var[3];
do _i = 1 to dim(var);
var_name = vname(var[_i]);
var_value = var[_i];
output;
end;
run;
proc sort data=for_ranking;
by var_name var_value;
run;
然后我们创建一个格式输入数据集,并使用排名作为标签。范围是(先前值 -> 当前值),标签是排名。我把如何处理关系留给你。
data for_fmt;
set for_ranking;
by var_name var_value;
retain prev_value;
if first.var_name then do; *initialize things for a new varname;
rank=0;
prev_value=.;
hlo='l'; *first record has 'minimum' as starting point;
end;
rank+1;
fmtname=cats(var_name,'F');
start=prev_value;
end=var_value;
label=rank;
output;
if last.var_name then do; *For last record, some special stuff;
start=var_value;
end=.;
hlo='h';
label=rank+1;
output; * Output that 'high' record;
start=.;
end=.;
label=.;
hlo='o';
output; * And a "invalid" record, though this should never happen;
end;
prev_value=var_value; * Store the value for next row.;
run;
proc format cntlin=for_fmt;
quit;
然后我们对其进行测试。
data test_b;
input obs_B VAR1 VAR2 VAR3;
var1r=put(var1,var1f.);
var2r=put(var2,var2f.);
var3r=put(var3,var3f.);
datalines;
1 15 150 2234
2 14 352 1555
3 36 251 1000
4 41 350 2011
5 60 553 5012
;;;;
run;
关于sas - 基于 SAS 中的另一个数据集对值进行排名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29194407/