sas - 基于 SAS 中的另一个数据集对值进行排名

标签 sas rank

假设我有两个数据集 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/

相关文章:

sas - 在不满足条件的情况下按 ID 删除所有观察结果

oracle - 通过SAS将新表写入Oracle数据库,写入时锁定表

仅对变量使用非缺失值的 SAS 函数?

mysql - 在 MYSQL 中排名并列结果

用 R 对矩阵的行 A 元素和列元素进行排序

nodes - Graphviz:在左侧对齐节点而不是居中(有答案)

java - SAS JavaOBJ 未找到 CLASSPATH

SAS:为什么宏中的 IN 运算符不是默认值?

MySQL返回用户排名最高的事件

python - 按单个整数对列进行排名