从长到宽转置数据

时间:2018-09-19 14:24:31

标签: sas transpose

我正在尝试将SAS中的数据从长格式转换为宽格式。我遇到的问题是我有多个要转置的列。我在下面有一些示例数据集来演示我正在尝试做的事情。我正在执行的实际数据集将非常大,我认为处理此问题的一种方法可能是转置各个列,然后在最后合并,但是我将继续执行的数据集正在要大得多(成千上万列),所以这是不可行的。

下面是我开始使用的数据:

data current_state;
input id $ att_1 $ att_2 $ att_3 $ att_4 $ att_5 $ Dollars;
datalines;
1 d234 d463 d213 d678 d435 50
2 d213 d690 d360 d145 d269 25
3 d409 d231 d463 d690 d609 10
;

下面是我希望转置的结果:

data desired_state;
input id $ d145 $ d213 $ d231 $ d234 $ d269 $ d360 $ d409 $ d435 $ d463 $ d609 $ d678 $ d690;
datalines;
1 0 50 0 50 0 0 0 50 0 0 50 0
2 25 25 0 0 25 25 0 0 0 0 0 25
3 0 0 10 0 0 0 10 0 10 10 0 10
;

我尝试了以下操作,但并没有达到预期的输出结果。

proc transpose data=current_state out=test1;
by id;
id att_1 att_2 att_3 att_4 att_5;
var Dollars;
run;

2 个答案:

答案 0 :(得分:1)

Proc TRANSPOSE没有用于“并行枢轴”到单行的语法-多个ID串联在一起成为列名的结果ID。

使用串行枢轴可以实现并行枢轴结果-首先枢轴到更高的矢量布局,然后再枢转到较宽的布局。

proc transpose data=current_state out=stage1_vector;
by id Dollars;
var att_1 att_2 att_3 att_4 att_5;
run;

proc transpose data=stage1_vector out=want;
by id;
id col1;
run;

want中的列顺序基于矢量布局中数据中col1的值外观。您可以通过创建虚拟记录来强制排序列的顺序,其中col1的值应按所需的出现顺序出现。

proc transpose data=current_state out=stage1_vector(drop=_name_);
by id Dollars;
var att_1 att_2 att_3 att_4 att_5;
run;

proc sort nodupkey data=stage1_vector(keep=col1) out=ids;
  by col1;
run;

data vector_view / view=vector_view;
  set ids stage1_vector;
run;

proc transpose data=vector_view out=want;
  by id;
  id col1;
run;

应该仔细考虑用零替换缺失值的要求,尤其是如果您要计算带有d *值的ID的数量(Proc MEANS等)时,尤其要注意这一点。无论如何,可以在转置后的步骤中完成替换。

data want;
  set want;
  array zerome d:;

  /* re-purpose _n_ temporarily as a loop index variable
   * that does not have to be explicitly dropped
   */
  do _n_ = 1 to dim(zerome);
    if missing(zerome(_n_)) then zerome(_n_) = 0;
  end;
run;

答案 1 :(得分:0)

这是一种完全动态的方式,但这可能不是最有效的。

  1. 转置为长格式
  2. 使用GLMMOD为每个D值创建一个0/1矩阵
  3. 用D重命名GLMMOD中的变量
  4. 将1转换为美元金额-供您选择。

        data current_state;
    input id $ att_1 $ att_2 $ att_3 $ att_4 $ att_5 $ Dollars;
    datalines;
    1 d234 d463 d213 d678 d435 50
    2 d213 d690 d360 d145 d269 25
    3 d409 d231 d463 d690 d609 10
    ;
    
    *transpose to long;
    proc transpose data=current_state out=long;
    by id dollars;
    var att_1-att_5;
    run;
    
    /*Run model within PROC GLMMOD for it to create design matrix
    Include all variables that might be in the model*/
    proc glmmod data=long outdesign=want outparm=p;
    class col1;
    model dollars = col1;
    run;
    
    /*Create rename statement automatically
    THIS WILL NOT WORK IF YOUR VARIABLE NAMES WILL END UP OVER 32 CHARS*/
    data p;
    set p;
    if _n_=1 and effname='Intercept' then var='Col1=Intercept';
    else var= catt("Col", _colnum_, "=", vvaluex(effname));
    run;
    
    proc sql;
    select var into :rename_list separated by " "
    from p;
    quit;
    
    
    /*Rename variables*/
    proc datasets library=work nodetails nolist;
    modify want;
    rename &rename_list;
    run;quit;
    
    
    proc print data=want;
    run;
    

https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-dummy-variables-Categorical-Variables/ta-p/308484