最近在论坛、群里面经常看到有人问数据转置相关的问题,那么今天小编就在来说一说数据集的转置,之前虽然也写过proc transpose相关的推文,那么今天我还要写...不仅仅要写这个!我还要写小编在数据转置上的成长历程...
数据转置难么?
数据集的转置难么?其实不难,在我刚学SAS的前俩周,我眼里的数据集转置是set、keep、rename,基础吧!Data步里面特别基础的知识!能数据集的转置?当然能。当时的小编做到的还是Epi的系统的项目的,接下来与小编来看一看一个实验室的检查的数据集转置!现在以及找不到当时的数据集了,就随便找了一个简化的版的数据来做实例。
将如上,小横表装置成纵表:如何用rename、keep、set来操作呢;见下代码
代码语言:javascript复制%macro test;
%do i=1 %to 3;
data temp&i.;
set lbb1(keep=subjid LBBORRES&i. LBBORUOT&i. LBBCLSIG&i. LBBCOM&i.);
LBTEST="&i.";
rename LBBORRES&i.=LBORRES LBBORUOT&i.=LBORUOT LBBCLSIG&i.=LBCLSIG LBBCOM&i.=LBBCOM;
run;
%end;
data final;
set temp1-temp3;
run;
%mend;
%test;
用的是最基础的语句的...基本上没有任何知识点啥的...转置成如下
既然横线转置成纵向,那么纵向在转置回去是不是也可以用这样的最通俗的语句实现呢?是的,见下面的代码!
代码语言:javascript复制%macro test;
%do i=1 %to 3;
data temp&i.;
set final;
where LBTEST="&i.";
rename LBORRES=LBBORRES&i. LBORUOT=LBBORUOT&i. LBCLSIG= LBBCLSIG&i. LBBCOM=LBBCOM&i.;
run;
proc sort data=temp&i. out=temp&i. sortseq=linguistic(numeric_collation=on);by SUBJID;quit;
%end;
data want;
merge temp1-temp3;
by subjid;
run;
%mend;
%test;
我升级了
前面的代码!请轻喷!这是我接触SAS后2周做测试项目,做的实验室转置方式!
写在这里,其实也是要说,转置真的不难!最基础的语句都能“简单”(原理简单,真实的情况代码写起来会很长)
只要不嫌麻烦!这种方式基本上能实现各种转置吧!在用这种方式,写了几百行代码后,看到带我的人就用几行代码解决了问题!然后,我就开始了学习数组~数组就开始陪伴我写转置很长一段时间了...(
其实现在也不怎么用数组了,数组也被我摒弃了...很久不写已经忘的差不多了,用词不当之处,还请各位大神指正一二).接着上面的那个例子来初识数组。用数组来试下横向转置成纵向~
代码语言:javascript复制data want;
set lbb1;
array ar1(*) LBBORRES1-LBBORRES3;
array ar2(*) LBBORUOT1-LBBORUOT3;
array ar3(*) LBBCLSIG1-LBBCLSIG3;
array ar4(*) LBBCOM1-LBBCOM3;
do i=1 to dim(ar1);
LBTEST=i;
LBORRES=ar1(i);
LBORUOT=ar2(i);
LBCLSIG=ar3(i);
LBBCOM=ar4(i);
output;
end;
keep subjid LBORRES LBORUOT LBCLSIG LBBCOM LBTEST;
run;
可能看着和上面代码差不多!其实不管在效率还是代码的精简上还是差很多的!只是小编的这个例子举的可能不太好!那么数组是否可以纵向转置成横向呢?是可以的,接下来就来看看数组纵向转置成横向在此处的应用!
代码语言:javascript复制proc sort data=want out=want sortseq=linguistic(numeric_collation=on);by subjid LBTEST;quit;
data want1;
set want;
by subjid LBTEST;
retain LBBORRES1-LBBORRES3 LBBORUOT1-LBBORUOT3 LBBCLSIG1-LBBCLSIG3 LBBCOM1-LBBCOM3 i ;
array ar1(*) LBBORRES1-LBBORRES3;
array ar2(*) LBBORUOT1-LBBORUOT3;
array ar3(*) LBBCLSIG1-LBBCLSIG3;
array ar4(*) LBBCOM1-LBBCOM3;
if first.subjid then i=1;
else i 1;
ar1(i)=LBORRES;
ar2(i)=LBORUOT;
ar3(i)=LBCLSIG;
ar4(i)=LBBCOM;
if last.subjid then output;
keep subjid LBBORRES: LBBORUOT: LBBCLSIG: LBBCOM: ;
run;
看起来是有些繁琐一些!是的,数组横向转置纵向的思维比较好理解,纵向转置成横向感觉理解起来不是那么方便自如!可能还是小编使用的不够熟练,所以才有这样的感觉!
进入主题array
开始进入本文的主要部分了,其实也是打算对数组进行一个简单的介绍,当然介绍的一维数组,多维数组以目前我的工作还没有接触到,所以我也没进行研究过,因此我这次也就不说了。当然数组的作用不局限于数据的转置,但小编数组使用最多的还是在数据转置的场景下,所以呀,例子也仅举转置。
首先,数组是什么,可以理解成在内存中开辟了一个空间,然后给这个空间安上凳子,将你需要放入这空间的东西(变量,字符串,数字等)对号入组,最后通过调用这个空间的名字(数组的名字),以及凳子号(数组的下脚标)来提取数据。小编是这样浅显的理解的...
如何定义数组?网上找了一个图,感觉还挺好的,见下图!
这里需要注意的是,定义数组的时候,数值型与字符型不能混合的一起。说到这儿,如果上面那段代码不keep seq name;数据集会是什么样的呢?
为啥数据集有这么多变量呢?而且数组变量名是不是很眼熟?数组的名称 数组的脚标,数组其实就类似一个大横表..那么这样创建数组是不是会影响运行的效率呢?当数据量大的时候,是特别的影响运行的效率的。有什么办法解决这个问题呢?可以创建数组的时候的声明一下数组是一个临时数组,这样数组的值就不会出现在数据集里面了,会提高一下运行的效率..接下来看下图。
虽然临时数组会提高运行效率,但是也有缺陷,需要慎用。一般我都不用的。这里的例子都是塞入固定的数值、字符串。当然还是可以塞入变量的,就如同最开始的转置的例子,就是往数组塞入变量。在就不在多举例子了,好像一维数组在就没有别的啥要注意的,奥,还有数组脚标不要越界了...不然就会出ERROR的~见下图
我又升级了
我用数组转置,我大概用了一年了,虽然一直知道transpose可以转置,当时由于种种原因没有对transpose好好了解一下,后来突然想换方式转置了,就对proc transpose做了一些学习,然后就不可自拔了
现在转置一般都用transpose了,因为效率确实比数组高,尤其针对大数据处理的时候!关于proc transpose结构我这里就不在说了,以前的推送多次有用到与专门写过了,可点击此处SAS Proc transpose过程步,当然也可以点击SAS-一条群消息引发的思考,当然还可以在此点击SAS- 100种数据compare的方式,你在用哪种?,里面都有transpose使用的实例。当然也可以不点击~因为下面,马上要有很多例子了~
我回答过的几个简单转置
例一:是一个简单的转置~
代码语言:javascript复制data have;
input Dependent $ obs orres;
cards;
AL_Mean 1 -41.4706
AL_Mean 2 10.7621
cr2_Mean 1 -1.2781
cr2_Mean 2 0.2003
Mn_Mean 1 -13.7115
Mn_Mean 2 4.0014
;
run;
proc sort data=have out=have ;by obs;;quit;
proc transpose data=have out=want(drop=_:);
by obs;
var orres;
id Dependent ;
run;
嗯!上面是利用proc transpose实现的过程,那么接下来在来看看array如何实现...
代码语言:javascript复制proc sql noprint;
select distinct Dependent into:varlist1 separated by " " from have order by Dependent ;
quit;
%put NOTE:&varlist1.;
proc sort data=have out=want sortseq=linguistic(numeric_collation=on);by obs Dependent ;quit;
data want1;
set want;
by obs Dependent ;
retain &varlist1. i ;
array ar1(*) &varlist1.;
if first.obs then i=1;
else i 1;
ar1(i)=orres;
if last.obs then output;
keep obs &varlist1.;
run;
说实话,这里用数组纵转横我还真不太擅长和习惯...接下来在看一个例子
这转置其实也是很简单的,不过得多操作几步!接下来看代码如何来试下~
代码语言:javascript复制data test;
input person $ city $ Age $ product $ Brand $;
cards;
A SH 22 P1 APPLE
A SH 22 P2 VIVO
B BJ 35 P3 HUAWEI
B BJ 35 P4 SAMSUNG
B BJ 35 P5 SAMSUN
C GZ 50 P5 MI
;
run;
proc sort data=test out=test ;by person city Age ;;quit;
data test;
set test ;
by person city Age ;
if first.person then x=1;
else x 1;
array aa[*] product brand;
do i=1 to dim(aa);
_Name_=strip(vname(aa[i]))||strip(vvalue(x));
Value=aa[i];
output ;
end;
keep person city Age _Name_ Value;
run;
proc transpose data=test out=test1(drop=_:);
by person city age;
var value;
run;
当然上面的代码不段用到数组,也用到了proc transpose。当然仅仅用transpose也是能实现的,只不过要多转几次!代码就不在这里贴了。
今天就这么多了,后续内容,敬请期待~