gpt4 book ai didi

algorithm - SAS:通过另一列查找一列总和的最佳方法是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:41:58 24 4
gpt4 key购买 nike

我想找出在 SAS 中执行分组依据的最佳方法,以便执行一些基准测试。我能想到的最简单的两种方式是Proc SQLProc means。这是 proc sql

中的示例


proc sql noprint;/* 耗时 6 分钟 */
创建表总和作为选择
ID,
总和(值)

兰丁
通过...分组
ID
;
辞职;

我认为有办法让它运行得更快

  • 先使用sasfile命令将数据载入内存
  • id 上创建索引

还有其他我可以使用的选项吗?我应该打开任何 SAS 选项以使此运行尽可能快吗?我不受 proc sql 或 proc means 的束缚,所以如果有更快的方法那么我很想知道它!!!

我的设置代码如下

options macrogen;
options obs=max sortsize=max source2 FULLSTIMER;
options minoperator SASTRACE=',,,d' SASTRACELOC=SASLOG;
options compress = binary NOSTSUFFIX;
options noxwait noxsync;
options LRECL=32767;

proc fcmp outlib=work.myfunc.sample;
function RandBetween(min, max);
return (min + floor((1 + max - min) * rand("uniform")));
endsub;
run;

options cmplib=work.myfunc;

data RandInt;
do i = 1 to 250000000;
id = RandBetween(1, 2500000);
val = rand("uniform");
output;
end;
drop i;
run;

我的SAS比较宏如下

%macro sasbench(dosql = N); %macro _; %mend;
%if &dosql. = Y %then %do;
proc sql noprint; /* took 6 mins */
create table summ as select
id,
sum(val)
from
randint
group by
id
;
quit;
%end;

proc means data=randint sum noprint;
var val ;
class id;
output out = summmeans(drop=_type_ _freq_) sum = /autoname;
run;
%mend;

%sasbench();
/**/
/*sasfile randint load;*/
/*%sasbench();*/
/*sasfile randint close;*/

proc datasets lib=work;
modify randint;
INDEX CREATE id / nomiss;
run;

%sasbench();

最佳答案

sasfile 只有在整个数据集可以适应 session ram 限制并且数据集将被多次使用时才有用。我想如果您的基准测试在同一个 sasfile 上包含多次运行/不同技术,这将是有意义的。

如果数据未按 id 排序,则 id 索引会有所帮助。当数据集按 id 预排序时,id 列元数据将设置 sortedby 标志,过程可以将其用于其自身的内部优化,但是不能保证。对于索引,使用 option msglevel=i 获取日志中有关处理期间索引选择的信息性消息。

最快的方法是直接寻址,但需要足够的内存来处理最大的 id 值作为数组索引:

  • array ids(250000000) _temporary_
  • ids(id) + 值

下一个最快的方法可能是基于散列的手工编码数组:

  • 在 SAS session 记录中搜索 Paul Dorfman 的论文

下一个最快的散列方法可能是具有键 suminc 的散列组件对象。

已编辑数据步骤以与评论保持一致

data demo_data;
do rownum = 1 to 1000;
id = ceil(100*ranuni(123)); * NOTE: 100 different groups, disordered;
value = ceil(1000*ranuni(123)); * NOTE: want to sum value over group, for demonstration individual values integers from 1..1000;
output;
end;
run;

data _null_;
if 0 then set demo_data(keep=id value); %* prep pdv ;
length total 8; %* prep keysum variable ;
call missing (total); %* prevent warnings ;
declare hash ids (ordered:'a', suminc:'value', keysum:'total'); %* ordered ensures keys will be sorted ascending upon output ;
ids.defineKey('id');
*ids.defineData('id'); % * not having a defineData is an implicit way of adding only the keys as data, only data + keysum variables are .output;
ids.defineDone();

* read all records and touch each hash key in order to perform tacit total+value summation;
do until (end);
set demo_data end=end;
if ids.find() ne 0 then ids.add();
end;

ids.output(dataset:'sum_value_over_id'); * save the summation of each key combination;
stop;
run;

注意:keysum变量只能有一个。

如果将 suminc 变量设置为始终为 1 而不是值,则 key 和将是计数而不是总数。

通过散列获得 sum 和 count over group 需要一个显式的 defineData 用于 count 和 sum 变量以及稍微不同的语句,例如:

declare hash ids (ordered:'a');
...
ids.defineData('id', 'count', 'total');
...
if ids.find() ne 0 then do; count=0; total=0; end;
count+1;
total+value;
ids.replace();
...

但是,如果已知值始终是自然数,并且已知组大小小于 10组大小限制,则可以使用 value 的 suminc 对计数进行数字编码+ 10-group size limit 并通过使用 count = (total - int(total)) * 10group 处理输出数据来对计数进行数字解码大小限制

对于已排序的数据,最快的方法很可能是带累加的 DOW 循环。

proc sort data=foo;
by id;
data sum_value_over_id_v2(keep=id total);
do until (last.id);
set foo;
by id;
total = sum(total, value);
end;
run;

您可能会发现 I/O 是性能的最大组成部分。

关于algorithm - SAS:通过另一列查找一列总和的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47255408/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com