我在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前两列已经排序了?
答案 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;
我得到的相关结果如下:
日志输出中的相关指标是用户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排序更快