将数据从长到大重塑

时间:2016-03-10 06:41:03

标签: sas

下面是我发现从长到宽重塑数据的示例。但我无法理解代码,尤其是它们替换空白的方式以及原因。有人可以帮我理解代码吗?

示例1:重塑一个变量

我们将从一个只有一个变量的小数据集开始重新整形。我们将使用变量year和faminc(用于家庭收入)来创建三个新变量:faminc96,faminc97和faminc98。首先,让我们看一下数据集并使用proc print来显示它。

DATA long ; 
  INPUT famid year faminc ; 
CARDS ; 
1 96 40000 
1 97 40500 
1 98 41000 
2 96 45000 
2 97 45400 
2 98 45800 
3 96 75000 
3 97 76000 
3 98 77000 
; 
RUN ;
PROC PRINT DATA=long ;
RUN ;
Obs    famid    year    faminc

 1       1       96      40000
 2       1       97      40500
 3       1       98      41000
 4       2       96      45000
 5       2       97      45400
 6       2       98      45800
 7       3       96      75000
 8       3       97      76000
 9       3       98      77000

现在让我们来看看这个节目。重塑过程的第一步是对标识变量(famid)排序数据(使用proc排序)并保存排序数据集(longsort)。接下来,我们编写一个数据步骤来进行实际的重塑。我们将按顺序解释数据步骤中的每个语句。

PROC SORT DATA=long OUT=longsort ;
 BY famid ;
RUN ;

DATA wide1 ;
  SET longsort ;
  BY famid ;

  KEEP famid faminc96 -faminc98 ;
  RETAIN faminc96 - faminc98 ;

  ARRAY afaminc(96:98) faminc96 - faminc98 ;

  IF first.famid THEN
  DO;
    DO i = 96 to 98 ;
      afaminc( i ) = . ;
    END;
  END;

  afaminc( year ) = faminc ;

  IF last.famid THEN OUTPUT ;

RUN;

3 个答案:

答案 0 :(得分:0)

这里的主要元素是SAS保留声明。 对数据集中的每个观察执行datastep。对于每次迭代,所有变量都设置为缺失,然后从数据集加载数据。 如果变量是RETAINed,它将不会被重置,但会保留上次迭代的信息。

BY famid ;

您的数据集已订购,而datastep正在使用by语句。这会初始化first.famidlast.famid。这些只是对于单个id组的第一次/最后一次观察而变为1的二进制文件。

RETAIN faminc96 - faminc98 ;

正如已经解释过的那样,faminc96 - faminc98会将其值从一个datastep迭代保持到下一个。

ARRAY afaminc(96:98) faminc96 - faminc98 ;

只是一个数组,所以你可以用数字而不是名字来调用变量。

  IF first.famid THEN
  DO;
    DO i = 96 to 98 ;
      afaminc( i ) = . ;
    END;
  END;

对于id组中的每个第一次观察,保留的变量都会被重置。否则,您将保留一个od-group到下一个od-group的值。同样可以通过IF first.famid then call missing(of afaminc(*));

完成
afaminc( year ) = faminc ;

根据年份将信息写入转置变量。

 IF last.famid THEN OUTPUT ;

将所有值写入新变量后,只将每个id-group中的一个观察值(最后一个)输出到新数据集。由于保留了变量,所以在这一点上它们都被填充了。

这个datastep是快速且​​有目的的构建。但通常你可以使用proc transpose

答案 1 :(得分:0)

这是与DO UNTIL进行比较和对比的一个很好的例子(最后。它取消了在FIRST.FAMID和LAST上丢失的RETAIN和INIT。测试何时输出。这些操作只是使用内置数据步骤循环的功能。

DATA long; 
   INPUT famid year faminc; 
   CARDS; 
1 96 40000 
1 97 40500 
1 98 41000 
2 96 45000 
2 97 45400 
2 98 45800 
3 96 75000 
3 97 76000 
3 98 77000 
;;;; 
   RUN;
proc print;
   run;
data wide;
   do until(last.famid);
      set long;
      by famid;
      ARRAY afaminc[96:98] faminc96-faminc98;
      afaminc[year]=faminc;
      end;
   drop year faminc;
   run;
proc print;
   run;

答案 2 :(得分:0)

我强烈推荐proc转置。它会让你的生活更轻松。

http://support.sas.com/resources/papers/proceedings09/060-2009.pdf