SAS转置超过100个变量

时间:2014-01-13 09:17:47

标签: sas

我有100个变量的数据集,前缀变量以及2013年到2022年。我想转置数据。请在下面找到示例。

ID MODEL A_2013 A_2014 ....A_2022 B_2013 B_2014...B_2022 C_2013..C_2022
1   NEW   0.5    0.2   ... 0.8    0.2    0.3     0.9    0.2     0.5
2   OLD   0.2    0.9   .... 0.9   0.5    0.6      0.2    0.6     0.6
3   NEW   0.2    0.3   .... 0.2   0.6     0.9     0.2    0.6     0.1

我想做

    ID MODEL YEAR    A      B     C 
    1  NEW   2013   0.5    0.2    0.2  
    1  NEW   2014   0.2    0.5    0.8
    1  NEW   2022   0.8    0.2    0.5

我该怎么做?

3 个答案:

答案 0 :(得分:3)

这可以通过使用数组的一个数据步骤来完成:

Data [Output] (keep=ID MODEL YEAR A B);

   set [Input];

   array arr_A{10} A_2013 - A_2022;
   array arr_B{10} B_2013 - B_2022;

   DO i=1 to 10;
      A=arr_A[i];
      B=arr_B[i];
      YEAR = 2012+i;
      OUTPUT;
   END;
RUN;

答案 1 :(得分:1)

请参阅以下代码,该代码使用两个PROC TRANSPOSE步骤和一个DATA STEP + 1 PROC SORT来实现您要查找的输出。这可能更有可能在使用DATA的单个ARRAYS步骤中完成。但是,大多数SAS程序员都应该采用以下方法。

/*sample data*/
data have;
INPUT ID MODEL $ A_2013 A_2014 A_2022 
B_2013 B_2014 B_2022
;
datalines;
1 NEW 0.5 0.2 0.1 0.4 3.4 12.89
2 OLD 0.5 0.2 0.3 0.4 3.4 12.5
3 NEW 0.5 0.2 0.1 0.2 3.4 12.4
4 OLD 0.5 0.2 4.1 0.4 3.4 12.0
5 NEW 0.2 0.1 0.3 0.4 3.1 12.1
6 OLD 2.5 1.2 2.1 1.4 2.4 1.2
;
run;
/*1st transpose: turn the input dataset from short and wide to long and thin*/
proc transpose data = have out = have_t(rename = (col1=value));
by id model;
run;

/*split the labels into two parts, segment & year*/
data have_t2;
length segment $8 year 8;
set have_t;
underScorePosition=index(_name_,'_');
segment = substr(_name_,1, underScorePosition-1);
year = input(substr(_name_,underScorePosition+1), 4.);
drop _name_;
run;
/*make sure values are properly sorted before passing to 2nd transpose*/
proc sort data = have_t2;
by id model year;
run;
/*2nd transpose: here turn  sgements into columns*/
proc transpose data = have_t2 out = want(drop =_name_);
by id model year;
id segment;
var value;
run;

输出:

ID  MODEL   year    A   B
1   NEW 2013    0.5 0.4
1   NEW 2014    0.2 3.4
1   NEW 2022    0.1 12.89
2   OLD 2013    0.5 0.4
2   OLD 2014    0.2 3.4
2   OLD 2022    0.3 12.5
3   NEW 2013    0.5 0.2
3   NEW 2014    0.2 3.4
3   NEW 2022    0.1 12.4
4   OLD 2013    0.5 0.4
4   OLD 2014    0.2 3.4
4   OLD 2022    4.1 12
5   NEW 2013    0.2 0.4
5   NEW 2014    0.1 3.1
5   NEW 2022    0.3 12.1
6   OLD 2013    2.5 1.4
6   OLD 2014    1.2 2.4
6   OLD 2022    2.1 1.2

答案 2 :(得分:1)

如果您使用视图进行变量重命名,则可以在2个直通中轻松实现此目的。

1 Proc Transpose

首先转置数据,以便只有4列:

  1. ID(id)
  2. 模型(型号)
  3. label_year组合( NAME
  4. 值(COL1)
  5. 请注意,我使用IF语句来消除所有OLD模型,因为我没有在您想要的输出中看到它们。

    proc transpose data=DATAINPUT out=TRANSPOSEOUTPUT;
        where MODEL='NEW';
        by id model;
    run;
    

    2数据步骤视图

    这里我们基本上将 NAME 分成标签和年份。此外,还有一些数据清理(删除 NAME &重命名COL1)

    data V_TRANSPOSEOUTPUT (drop=_NAME_ rename=(COL1=value)) /view=V_TRANSPOSEOUTPUT;
        length ID 8;
        length model $3;
        length year 8;
        length label $1;
        set TRANSPOSEOUTPUT;
        label=scan(_NAME_,1,'_');
        year=scan(_NAME_,2,'_');
    run;
    

    3 Proc Tabulate(而不是proc报告)

    我发现proc制表比proc报告更合适,因为 - 至少在我的意见中 - 构建交叉表更容易。至少,根据您的评论,您希望将所需的输出显示为报告,而不是数据集。

    proc tabulate data=V_TRANSPOSEOUTPUT;
        table id*model*year,label*value;
        class id model year year label;
        var value;
    run;
    

    我测试了这个,我的输出与你写的略有不同,但我怀疑你在写出你想要的结果时犯了几个错误。 ;)