在SAS中对几乎排序的数据集进行排序

时间:2014-11-25 16:15:17

标签: sorting sas sorted

我在SAS中有一个大型数据集,我知道它几乎已经排序;我知道第一级和第二级是排序的,但第三级不是。此外,第一级和第二级包含大量不同的值,因此当我知道它已经处于正确的顺序时,再次对前两列进行排序更不可取。数据示例如下所示:

ID  Label    Frequency
1   Jon      20
1   John     5
2   Mathieu  2
2   Mathhew  7
2   Matt     5
3   Nat      1
3   Natalie  4

在proc排序上使用“presorted”选项似乎只检查数据是否按每个键排序,否则它会完整排序数据。有没有办法告诉SAS前两列已经排序了?

1 个答案:

答案 0 :(得分:8)

如果您之前已按前2个变量对数据集进行排序,那么无论数据集上的sortedby信息如何,SAS都会花费较少的CPU时间对其进行排序*。这是大多数不错的排序算法的自然属性 - 对已经几乎排序的东西进行排序的工作要少得多。

*只要您不在force语句中使用proc sort选项,这会强制它进行冗余排序。

这是我跑的一个小测试:

option fullstimer;
/*Make sure we have plenty of rows with the same 1 + 2 values, so that sorting by 1 + 2 doesn't imply that the dataset is already sorted by 1 + 2 + 3*/
data test;
    do _n_ = 1 to 10000000;
        var1 = round(rand('uniform'),0.0001);
        var2 = round(rand('uniform'),0.0001);
        var3 = round(rand('uniform'),0.0001);
        output;
    end;
run;

/*Sort by all 3 vars at once*/
proc sort data = test out = sort_all;
    by var1 var2 var3;
run;

/*Create a baseline dataset already sorted by 2/3 vars*/
/*N.B. proc sort adds sortedby information to the output dataset*/
proc sort data = test out = baseline;
    by var1 var2;
run;

/*Sort baseline by all 3 vars*/
proc sort data = baseline out = sort_3a;
    by var1 var2 var3;
run;

/*Remove sort information from baseline dataset (leaving the order of observations unchanged)*/
proc datasets lib = work nolist nodetails;
    modify baseline (sortedby = _NULL_);
    run;
quit;

/*Sort baseline dataset again*/
proc sort data = baseline out = sort_3b;
    by var1 var2 var3;
run;

我得到的相关结果如下:

  • SAS花了8秒钟对所有3个变量对原始完全未排序的数据集进行排序。
  • SAS花了4秒时间从已经按2/3变量排序的基线数据集开始按3/3排序。
  • SAS从相同的基线数据集开始,在从中移除排序信息后,需要4秒钟才能按3/3排序。

日志输出中的相关指标是用户CPU时间量。

当然,如果几乎排序的数据集非常大并且包含许多其他变量,您可能希望在替换它时避免由于写入开销而导致的排序。您可以采用的另一种方法是创建一个复合索引 - 例如,这将允许您通过组处理执行相关操作。

/*Alternative option - index the 2/3 sorted dataset on all 3 vars rather than sorting it*/
proc datasets lib = work nolist nodetails;
    /*Replace the sort information*/
    modify baseline(sortedby = var1 var2);
    run;
    /*Create composite index*/
    modify baseline;
    index create index1 = (var1 var2 var3);
    run;
quit;

创建索引需要读取整个数据集,排序也是如此,但只有一小部分工作涉及再次写出来,并且在某些情况下可能比2/3到3/3排序更快