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

Nic*_*ick 8 sorting sorted sas

我在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前两列已经排序?

use*_*489 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;
Run Code Online (Sandbox Code Playgroud)

我得到的相关结果如下:

  • SAS花了8秒钟对所有3个变量对原始完全未排序的数据进行排序.
  • 从已经按2/3变量排序的基线数据开始,SAS花了4秒钟从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;
Run Code Online (Sandbox Code Playgroud)

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