SAS中是否有一种有效的转置大表的方法
我在SAS中有一个数据集需要转置。它的形式是 id日期类型值 我需要把它转换成 类型1的id日期值类型2的id日期值 有什么有效的方法来实现这一点吗?我的数据是huuuge 比如,SAS中是否有一种有效的转置大表的方法,sas,transpose,Sas,Transpose,我在SAS中有一个数据集需要转置。它的形式是 id日期类型值 我需要把它转换成 类型1的id日期值类型2的id日期值 有什么有效的方法来实现这一点吗?我的数据是huuuge 比如, data one; input ID date type $ value; cards; 1 2001 A 2 1 2002 A 4 1 2001 B 3 2 2001 B 1 2 2002 A 5 2 2002 C 2 2 2003 C 5 3 2001 B 6 4 2002 B 8 4 2003 B 4
data one;
input ID date type $ value;
cards;
1 2001 A 2
1 2002 A 4
1 2001 B 3
2 2001 B 1
2 2002 A 5
2 2002 C 2
2 2003 C 5
3 2001 B 6
4 2002 B 8
4 2003 B 4
4 2001 A 2
;
我想把它转换成以下形式;(最后三列为valA、valB、valC)
PROC-TRANSPOSE将非常非常有效地完成这项工作,我敢说,它与任何其他数据库管理系统中最有效的方法相当或更好。您的数据也已经针对该方法进行了完美的组织。您只需要按ID日期排序,除非您已经有了该组合的索引(如果您有数十亿条记录,这是必要的)。除非您有足够的内存将其全部放在内存中,否则没有其他解决方案能与之媲美——对于这种大小的数据集来说,这是相当疯狂的(即使10亿条记录也至少需要7GB,如果您有数百万个ID,那么它显然不是一个1字节的ID;我猜是25-30GB或更多) 在我的系统上进行的简单测试,包括以下内容:
data one;
do id = 1 to 1e6;
do date = '01JAN2010'd to '01JAN2012'd;
type = byte(ceil(ranuni(7)*26)+64);
value = ceil(ranuni(7)*20);
output;
end;
end;
run;
proc sort data=one;
by id date;
run;
proc transpose data=one out=want;
by id date;
id type;
var value;
run;
该数据集压缩了约20GB(OPTIONS COMPRESS=YES)。最初写大约需要4分15秒,排序需要11分钟,转置需要45分钟,写一个大约100GB的压缩文件。我想这是你能做的最好的了;在这45分钟中,可能有20分钟以上的数据被写出来(数据集大5倍,写出来的时间将超过5倍,加上压缩开销);我当时也在做其他事情,所以CPU时间可能有些膨胀,因为它没有得到我的整个处理器(这是我的桌面,一个4核的i5)。我不认为这是特别不合理的处理时间
你可以考虑一下你的需求,也许转座不是你真正想要的——你真的想把你的桌子弄得那么多吗?你很有可能在不转换整个数据集的情况下实现你的实际目标(你的分析等)
if first.date then a=.;b=.;c=.;d=.;
必须替换为:
if first.date then do;
a=.;b=.;c=.;d=.;
end;
或
也代替
if last.date then do; output; a=.;b=.;c=.;d=.; end;
现在,这应该足够了:
if last.date then output;
我想在大数据上,datastep总是比PROC TRANSPOSE更高效。限制是您必须找出转置变量的不同值,并为这些值创建新变量。我认为这就是PROC TRANSPOSE的开销——它首先找出值。
(很抱歉,我编辑了您自己的答案,因此现在可能不清楚问题出在哪里。)另一种数据步骤方法(): 在我的系统上,使用Joe使用的1/10大小的数据集,排序需要2分钟,使用proc transpose需要9分40秒。道琼斯指数在7分4秒内完成了同样的事情。在这个特定的场景中,它并不令人印象深刻,但它比proc转置有一个很大的优势:您可以使用它在一个过程中转置多个变量。以下是我使用的代码:
data one;
do id = 1 to 1e5;
do date = '01JAN2010'd to '01JAN2012'd;
type = byte(ceil(ranuni(7)*26)+64);
value = ceil(ranuni(7)*20);
output;
end;
end;
run;
data two;
do _n_ = 1 by 1 until(last.DATE);
set one;
array vals[26] val65-val90;
by ID DATE;
do i = 1 to 26;
if type = byte(64 + i) then vals[i] = value;
end;
end;
drop value i;
run;
动态重命名所有26个转置类型变量有点棘手,但这可以通过调用执行完成:
data _null_;
call execute('proc datasets lib = work nolist;');
call execute('modify two;');
call execute('rename');
do i = 1 to 26;
call execute(compress('val' || i + 64) || ' = ' || compress('val' || byte(64+i)));
end;
call execute(';');
call execute('run;');
call execute('quit;');
run;
您是否知道
proc transpose
?如果有比为这项工作设计的proc
更有效的方法,我会感到惊讶。我知道proc transpose
但是还有其他方法吗?因为我的数据集有超过10亿个观测值(数百万个ID,几乎每个ID都有近千个日期,以及8种不同的类型)。是否有使用其他功能(如保留等)的快捷方式?谢谢。根据我对SAS效率的理解,几乎任何可以在proc
中完成的事情都应该在proc
中完成。使用数据步骤通常效率要低得多;如果您使用的是SPDE,那么您可以跳过排序,并且可能可以从中获得非常好的性能,远远好于我在这里得到的性能。
if last.date then output;
proc sort data = one;
by ID date;
run;
data two;
do _n_ = 1 by 1 until(last.date);
set one;
by ID DATE;
if type = "A" then valA = value;
else if type = "B" then valB = value;
else if type = "C" then valC = value;
end;
drop value;
run;
data one;
do id = 1 to 1e5;
do date = '01JAN2010'd to '01JAN2012'd;
type = byte(ceil(ranuni(7)*26)+64);
value = ceil(ranuni(7)*20);
output;
end;
end;
run;
data two;
do _n_ = 1 by 1 until(last.DATE);
set one;
array vals[26] val65-val90;
by ID DATE;
do i = 1 to 26;
if type = byte(64 + i) then vals[i] = value;
end;
end;
drop value i;
run;
data _null_;
call execute('proc datasets lib = work nolist;');
call execute('modify two;');
call execute('rename');
do i = 1 to 26;
call execute(compress('val' || i + 64) || ' = ' || compress('val' || byte(64+i)));
end;
call execute(';');
call execute('run;');
call execute('quit;');
run;