SAS-100种数据转置的方法,你在用哪种?

2019-10-21 16:19:38 浏览数 (1)

最近在论坛、群里面经常看到有人问数据转置相关的问题,那么今天小编就在来说一说数据集的转置,之前虽然也写过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也是能实现的,只不过要多转几次!代码就不在这里贴了。

今天就这么多了,后续内容,敬请期待~

0 人点赞