我在SAS中有一个我需要转置的数据集。它有形式 id日期类型值 我需要把它转换成 id date valueoftype1 valueoftype2 ...
有没有有效的方法来实现这一目标?我的数据是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
4 2001 A 2
;
我希望将其转换为以下形式; (最后三列是valA,valB,valC)
1 2001 2 3 .
1 2002 4 . .
2 2001 . 1 .
2 2002 5 . 2
2 2003 . . 5
3 2001 . 6 .
4 2001 2 . .
4 2002 . 8 .
4 2003 . 4 .
答案 0 :(得分:2)
PROC TRANSPOSE将非常非常有效地执行此操作,我冒昧地说,与其他任何DBMS的最有效方法相同或更好。您的数据也已经为该方法组织得很好。您只需按ID DATE进行排序,除非您已经拥有该组合的索引(如果您有数十亿条记录是必需的IMO)。没有其他解决方案可以接近,除非你有足够的内存将它全部放在内存中 - 这对于那个大小的数据集来说相当疯狂(即使是10亿条记录也至少有7GB,如果你有数百万的ID那么它就清楚了不是一个1字节的ID;我猜是25-30 GB或更多。)
proc sort data=one;
by id date;
run;
proc transpose data=one out=want;
by id date;
id type;
var value;
run;
对我的系统进行了一次天真的测试,其中包括以下内容:
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分钟到PROC TRANSPOSE,写了一个~100GB的压缩文件。我猜这是你能做的最好的事情;在这45分钟内,超过20分钟可能写出来(5倍大的数据集将占用超过5倍的时间来写出来,加上压缩开销);我当时也在做其他事情,因此CPU时间可能会膨胀,因为它没有得到我的整个处理器(这是我的桌面,4核i5)。我认为这根本不是特别不合理的处理时间。
您可能会考虑查看自己的需求,也许转置并不是您想要的 - 您真的想长大吗?您可以在不转置整个数据集的情况下实现您的实际目标(您的分析/等)。
答案 1 :(得分:0)
if first.date then a=.;b=.;c=.;d=.;
必须替换为:
if first.date then do;
a=.;b=.;c=.;d=.;
end;
或
if first.date then call missing(a,b,c,d);
也代替
if last.date then do; output; a=.;b=.;c=.;d=.; end;
现在,它应该足够了:
if last.date then output;
我猜一个datastep总是比大数据上的PROC TRANSPOSE更有效率。限制是您必须找到转置变量的不同值并为这些变量创建新变量。我认为这是PROC TRANSPOSE的开销 - 它首先找出值。 (对不起,我编辑了你自己的答案,所以现在可能还不清楚是什么问题。)
答案 2 :(得分:0)
替代数据步骤方法(DOW-loop):
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;
在我的系统上,使用数据集大小为Joe使用的1/10,排序需要2分钟,使用proc转置需要9分40秒。 DOW循环在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个转置类型变量有点棘手,但这可以通过调用execute来完成:
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;