如何在SAS中使用id变量的多个观测值来转换数据?

如何在SAS中使用id变量的多个观测值来转换数据?,sas,transpose,Sas,Transpose,当我的id变量多次出现时,我想知道在SAS中转置数据的最佳方法。我知道我可以在proc transpose语句中使用let选项来实现这一点,但我不想删除任何数据,因为我打算计算平均值 以下是我的数据和代码示例: data grades; input student testnum grade; cards; 1 1 30 1 1 25 1 2 45 1 3 67 2 1 22 2 2 63 2 2 12 2 2 77 3 1

当我的id变量多次出现时,我想知道在SAS中转置数据的最佳方法。我知道我可以在proc transpose语句中使用let选项来实现这一点,但我不想删除任何数据,因为我打算计算平均值

以下是我的数据和代码示例:

data grades;
input student testnum grade;
cards;
1   1   30
1   1   25
1   2   45
1   3   67
2   1   22
2   2   63
2   2   12
2   2   77
3   1   22
3   1   17
3   2   14
3   4   17
;
run;

proc sort data=grades;
    by student testnum;
run;

proc transpose data=grades out=trgrades;
    by student;
    id testnum;
    var grade;
run;
以下是我希望生成的数据集的外观:

student testnum1 testnum2 testnum3 testnum4   avg12     avg34
1         30        45      67       .         33.33     67    
1         25        .        .       .         33.33     67
2         22        63       .       .         43.5      .
2         .         12       .       .         43.5      .
2         .         77       .       .         43.5      .
3         22        14       .      17         53        17
3         17        .        .       .         53        17
我想使用这个新的数据集(不确定如何创建)来创建新的列,这些列是一个学生的所有testnum1和testnum2的平均分数(avg12)和一个学生的所有TestNum3和testnum4的平均分数(avg34)

也许有一种更有效的方法可以做到这一点,但我被难倒了。
任何建议都非常感谢。

如果您真正需要的是每个学生的所有测试1和2的平均值,以及测试3和4的平均值,那么您根本不需要转换。您只需执行一个简单的数据步骤:

data grouped;
   set grades;
   if testnum In (1,2) then group=1;
   else if testnum in (3,4) then group=2;
run;
然后一个基本的
过程意味着

proc means data=grouped;
   by student group;
   var grade;
   output out=averages mean=groupaverage;
run;
如果您需要单个观测值中的平均值,您可以轻松地将
平均值
数据集转置

proc transpose data=grades out=trgrades;
    by student;
    id group;
    var grade;
run;

更新:

正如@Keith所提到的,使用一种格式对测试进行分组也是一个很好的选择。跳过数据步骤,创建如下格式:

proc format;
   value TestGroup
      1,2 = 'Tests 1 and 2'
      3,4 = 'Tests 3 and 4'
   ;
run;
然后,
proc意味着
变成:

proc means data=grouped;
   by student testnum;
   var grade;
   format testnum TestGroup.;
   output out=averages mean=groupaverage;
run;
结束更新


如果出于某种原因,您真的需要在一次观察中获得所有测试分数,那么我建议使用数据步骤使它们唯一可识别。使用
by
testnum.first
retain
,以及一个简单的计数器,为每个分数分配一个
重做的编号。现在,转置使用
retake
testnum
作为
id
变量。你应该能从那里找到答案


我现在真的希望我不是为你做SAS作业。

如果你真正需要的是每个学生的所有测试1和2,以及3和4的平均值,那么你根本不需要转换。您只需执行一个简单的数据步骤:

data grouped;
   set grades;
   if testnum In (1,2) then group=1;
   else if testnum in (3,4) then group=2;
run;
然后一个基本的
过程意味着

proc means data=grouped;
   by student group;
   var grade;
   output out=averages mean=groupaverage;
run;
如果您需要单个观测值中的平均值,您可以轻松地将
平均值
数据集转置

proc transpose data=grades out=trgrades;
    by student;
    id group;
    var grade;
run;

更新:

正如@Keith所提到的,使用一种格式对测试进行分组也是一个很好的选择。跳过数据步骤,创建如下格式:

proc format;
   value TestGroup
      1,2 = 'Tests 1 and 2'
      3,4 = 'Tests 3 and 4'
   ;
run;
然后,
proc意味着
变成:

proc means data=grouped;
   by student testnum;
   var grade;
   format testnum TestGroup.;
   output out=averages mean=groupaverage;
run;
结束更新


如果出于某种原因,您真的需要在一次观察中获得所有测试分数,那么我建议使用数据步骤使它们唯一可识别。使用
by
testnum.first
retain
,以及一个简单的计数器,为每个分数分配一个
重做的编号。现在,转置使用
retake
testnum
作为
id
变量。你应该能从那里找到答案


我现在真的希望我不仅仅是为你做SAS作业。

你可以创建一个testnum分组格式,这样就不需要创建额外的变量。Proc意味着将按格式化值分组。非常好,@Keith。我会把这个选项添加到我的答案中。谢谢,这正是我想做的。我原本打算只取最后一个。student,如果我能让我的数据如上面示例中所示,那么每个学生只剩下一行,其中一列为avg12,另一列为avg34,但这非常有效。这不是一个家庭作业问题,所以不用担心。您可以创建一个格式来分组testnum,这样就不需要创建额外的变量。Proc意味着将按格式化值分组。非常好,@Keith。我会把这个选项添加到我的答案中。谢谢,这正是我想做的。我原本打算只取最后一个。student,如果我能让我的数据如上面示例中所示,那么每个学生只剩下一行,其中一列为avg12,另一列为avg34,但这非常有效。这不是家庭作业问题,所以不用担心。