【问题标题】:ranking within rows of a data set [sas]在数据集的行内排名 [sas]
【发布时间】:2012-12-21 13:28:20
【问题描述】:

假设我有一个包含n 行和p 列的数据集,这样数据集中的每个条目都包含一个实数。我正在寻找一种方法来对每行中的 p 列进行排名。这个排名的输出应该是一个长度-p 的排名向量,它考虑了平局。

所以,假设我的数据集有 5 列。第一行可能类似于row 1 = {10, 13, 3, 3, -4}。我想对这一行执行一些操作,最后得到结果row 1 ranks = {3, 4, 2, 2, 1}。第二行可能类似于row 2 = {8, 3, -6, 5, 2},而这一行的结果应该是row 2 ranks = {5, 3, 1, 4, 2}

此功能是否在 SAS 中实现?我生成了不考虑平局的代码,但它们经常出现,以至于要花费不合理的时间来纠正不正确的行排名。

【问题讨论】:

  • @itzy proc rank 在列中排名,而不是在行中。
  • @Joe 我有可用的 IML,但我不使用它。
  • 我很好奇这个在你的编程中的最终用途。您打算如何使用它将驱动最终的非矩阵解决方案(即非 IML 或 R)......它可以通过创建一个仅具有排名的新数据集(就像 IML 将作为矩阵一样)轻松解决,或通过添加新变量(如 Bob 的解决方案),或通过添加带有等级的新行......即使是标准化结构也可能最适合结果数据的某些用途。
  • @Joe 最后我创建了一个新的数据集。对于上下文:我正在开展一个项目,使用均方误差比较不同条件下的各种方差估计量。我使用这些排名来制作视觉辅助工具。还要提一下,我并不反对使用 PROC IML,只是过去没有使用过。

标签: sas


【解决方案1】:

有趣的问题;这是一种可能的解决方案:

data have;
   p1=10; p2=13; p3=3;  p4=3; p5=-4; output;
   p1=8;  p2=3;  p3=-6; p4=5; p5=2;  output;
run;

data want;
   set have;
   array p(*) p1-p5;
   array c(*) c1-c5;
   array r(*) r1-r5;

   /* Copy vector to temp array and sort */
   do i=1 to dim(p); 
      c(i) = p(i); 
      end;
   call sortn(of c(*));

   /* Search new sorted array for the original position */
   do i=1 to dim(c);
      if i = 1 then rank=1;
      else if c(i) ne c(i-1) then rank + 1;
      do j=1 to dim(p);
         if p(j) = c(i) then do;
            r(j) = rank;
            end;
         end;
      end;

   /* PUT statement to see result in log */
   put +3 p(*)
     / +3 c(*)
     / +3 r(*);

   drop i j rank c1-c5;
run;

【讨论】:

    【解决方案2】:

    在我看来,您需要多个数组来执行此操作。

    1. 数组 1:存储排名的数组
    2. 数组 2:对值进行排序的数组
    3. 数组 3:未更改的原始数据

    我现在没有时间编写代码,但是使用这样的东西会做很多繁重的工作:

    http://support.sas.com/kb/24/754.html

    【讨论】:

    • 看起来@BobDuell 写了这段代码,所以我接受了他的回答。不过,我非常感谢您的回复。
    【解决方案3】:

    即使 OP 说他不使用 IML 以防其他人发现这对搜索它有用,也不妨添加它。 IML 确实是解决这个问题最简单的方法,因为它本质上是一个向量/矩阵问题......

    proc iml;
    p={10 13 3 3 -4, 5 6 5 2 3};
    r=j(2,5,.);
    print p r;
    do i = 1 to nrow(p);
      r[i,]=ranktie(p[i,]);
    end;
    print p r;
    quit;
    

    它对尝试的处理与 OP 略有不同,因此需要一些工作才能使其与请求的解决方案完全相同 - 但一般来说,1,2.5,2.5,4,5 [或 1,2,2,4 ,5] 可能是您真正想要的,而不是 1,2,2,3,4。当 2 和 3 打成平手时,4 和 5 应该保持 4 和 5,而不是移动到 3 和 4。

    【讨论】:

    • 有没有使用 PROC IML 输入和输出数据集的简单方法?
    • 有 - support.sas.com/documentation/cdl/en/imlug/63541/PDF/default/… 第 7 章。不过,IML 与 SAS 有很大不同 - 如果您熟悉的话,它与 R 更相似。
    • 我对 R 比对 SAS 更熟悉。在切换之前,我使用 R 将近 4 年。我相信IML和我会成为很好的朋友...
    • 优秀。 IML 还允许您调用 R 函数(我相信,甚至可以使用 R 语法),这样可能会简化您对 SAS 的介绍。
    【解决方案4】:

    只是为了好玩,鉴于 OP 的回答是想要一个带有等级的新数据集,这里是 PROC RANK 方法。可能不会比数据步骤快,但在多种情况下使用起来可能更简单、更容易,并且还有一个额外的优势,即您不会在编码中真正犯错(不会真正崩溃)。

    data have;
    input id x1-x5;
    datalines;
    1 10 13 3 3 -4
    2 5 6 5 2 3
    ;;;;
    run;
    
    proc transpose data=have out=temp;
    by id;
    var x1-x5;
    run;
    proc rank data=temp out=temprank;
    var col1;
    by id;
    run;
    proc transpose data=temprank out=want(drop=_name_ _label_);
    by id;
    var col1;
    id _name_;
    run;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多