有时候数据分析的时候,总是需要把数据颠来倒去,从不同的角度分析N遍,SAS不但提供彪悍的统计分析程序,还提供了整理数据的辅助语句,每次都能把数据整理有条有理的。众所周知,SAS在清洗整理数据方面(ETL)的能力强大无比。很多SASor在垂涎和试用R语言提供新奇的分析和绘图模块时,不忘了先在SAS里面把数据整得服服帖帖的。
下面把自己遇到几个不那么常规的矩阵转置收集一下,它们都用到了增加辅助变量这一小技巧,尽管简单,其实都非常实用。
例1, 最近遇到一个需要对数据集进行操作的小问题,在SAS帮助proc transpose里面没找到例子,数据形式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | data ex; input group $ var1 var2 ; cards; a 1 5 a 2 6 a 3 7 b 3 7 b 4 8 b 5 9 c 3 4 c 6 8 ; run; |
1 2 3 4 5 6 7 8 9 | data ccc(keep=group v new_var); set ex; array arr var1 var2; do over arr; v=vname(arr); new_var=arr; output; end; run; |
1 2 3 4 5 6 7 8 9 10 | data sxl; set ex; tem_N =_N_; run; proc transpose data=sxl out=sxl2(drop= tem_N) NAME=v prefix=New_var; var var:; by group tem_N; run; |
不要以为很简单,看似简单技巧,其实可以秒杀一片问题。具体可以参看论坛里面的类似问题:这个问题的第一步:http://bbs.pinggu.org/thread-996735-1-1.html ,还有此问题第一步:http://bbs.pinggu.org/thread-970841-1-1.html 等等;还有hssnow的博客文章:http://hssnow.name/2011/04/dataset-transformation/ 中的问题。
例2, 这是在网上搜到的webgu的一篇博文讨论的问题,见:http://blog.sina.com.cn/s/blog_41889b900100vk1w.html。
下面这个转换比较麻烦,需要用到3次矩阵转置,与webgu的方法相比,这个更具有通用性。比如说在原数据再增加一个变量(即增加一列),下面代码照常Ok。
1 2 3 4 5 6 7 8 9 10 11 | data ex1; input name $ date res; cards; amy 2323 111 amy 2323 555 amy 1111 855 bob 3333 645 bob 0994 354 bob 4344 954 ; run; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | proc transpose out=ex2; by name; run; data ex3; set ex2; num=_N_; run; proc sort data=ex3 out=ex3; by _name_; run; proc transpose data=ex3 out=ex4; var col:; by _name_ ; id name; run; proc sort data=ex4 out=ex4; by _name_; run; data ex5; set ex4; by _name_; if first._name_ then nb=0; nb+1; name=catt(_name_,nb); output; run; proc transpose name=id; var amy bob; id name; run; |
如果你感兴趣,可以贴个代码试试。
最后需要提醒一下,SAS转置存在一定的缺点,就是数据集太大的时候,需要消耗太大的内存,导致死机。
附一篇讲述SAS转置语句的语法示意图文章,比较形象,见: http://www.nesug.org/proceedings/nesug05/how/how5.pdf
原创文章: ”SAS转置技巧 — 辅助变量“,转载请注明: 转自SAS资源资讯列表
本文链接地址: http://saslist.net/archives/255
第一个问题,我是用土办法,两个步骤重命名变量得到
data a;
input grp $ a b;
datalines;
a 1 5
a 2 6
a 3 7
b 3 7
b 4 8
b 5 9
c 3 6
c 6 8
;
data a1(rename=(b=a));
set a ;
keep grp b;
run;
data combine;
set a1 a(drop=b);
run;
可以这样凑,但如果原数据是下面这样,则需要更多的凑,不够通用。
data a;
input grp $ a b c d;
datalines;
a 1 5 2 5
a 2 6 3 5
a 3 7 3 5
b 3 7 3 5
b 4 8 3 5
b 5 9 3 5
c 3 6 3 3
c 6 3 3 5
;
不过,如果列数多的时候,这个土方法就坑爹了。还是用矩阵好
例2我试了两种方法,其中一个不用PROC TRANSPOSE,详见http://www.xianhuazeng.com/cn/?p=446
data步用得不错,效率会有所提高。
顺便把代码转一下:
data want;
retain NUM 0;
array VARL[6] DATE1 RES1 DATE2 RES2 DATE3 RES3;
do until(last.NAME);
set ex1;
by NAME;
if first.NAME then NUM=0;
NUM=NUM+1;
VARL[NUM]=DATE;
NUM=NUM+1;
VARL[NUM]=RES;
end;
drop NUM DATE RES;
run;
proc transpose data=ex1(drop=res) out=ex1_1;
var date;
by name;
proc transpose data=ex1(drop=date) out=ex1_2;
var res;
by name;
data ex2;
merge ex1_1(rename=(name=id col1=date1 col2=date2 col3=date3) drop=_name_)
ex1_2(rename=(name=id col1=res1 col2=res2 col3=res3) drop=_name_);
run;