SAS - 将单列拆分为两个基于非二进制ID列的值

时间:2017-07-11 16:39:26

标签: sas

我的数据如下:

wait-notify

我想根据data have; length group 8 replicate $ 1 day 8 observation 8 ; input (_all_) (:); datalines; 1 A 1 0 1 A 1 5 1 A 1 3 1 A 1 3 1 A 2 7 1 A 2 2 1 A 2 4 1 A 2 2 1 B 1 1 1 B 1 3 1 B 1 8 1 B 1 0 1 B 2 3 1 B 2 8 1 B 2 1 1 B 2 3 1 C 1 1 1 C 1 5 1 C 1 2 1 C 1 7 1 C 2 2 1 C 2 1 1 C 2 4 1 C 2 1 2 A 1 7 2 A 1 5 2 A 1 3 2 A 1 1 2 A 2 0 2 A 2 5 2 A 2 3 2 A 2 0 2 B 1 0 2 B 1 3 2 B 1 4 2 B 1 8 2 B 2 1 2 B 2 3 2 B 2 4 2 B 2 0 2 C 1 0 2 C 1 4 2 C 1 3 2 C 1 1 2 C 2 2 2 C 2 3 2 C 2 0 2 C 2 1 3 A 1 4 3 A 1 5 3 A 1 6 3 A 1 7 3 A 2 3 3 A 2 1 3 A 2 5 3 A 2 2 3 B 1 2 3 B 1 0 3 B 1 2 3 B 1 3 3 B 2 0 3 B 2 6 3 B 2 3 3 B 2 7 3 C 1 7 3 C 1 5 3 C 1 3 3 C 1 1 3 C 2 0 3 C 2 3 3 C 2 2 3 C 2 1 ; run; observation分成两列。

day

敏锐的SO读者会注意到我提出了基本相同的问题previously。但是,由于SAS对"级别"的痴迷由于用于分割感兴趣的变量的变量不是二进制的,因此该解决方案并不是一般的。

和" by groups"

直接尝试,会发生以下情况:

                                        observation_    observation_
           Obs    group    replicate        day_1           day_2

             1      1          A              0               7
             2      1          A              5               2
             3      1          A              3               4
             4      1          A              3               2
             5      1          B              1               3
             6      1          B              3               8
             7      1          B              8               1
             8      1          B              0               3
             9      1          C              1               2
            10      1          C              5               1
            11      1          C              2               4
            12      1          C              7               1
            13      2          A              7               0
            14      2          A              5               5
            15      2          A              3               3
            16      2          A              1               0
            17      2          B              0               1
            18      2          B              3               3
            19      2          B              4               4
            20      2          B              8               0
            21      2          C              0               2
            22      2          C              4               3
            23      2          C              3               0
            24      2          C              1               1
            25      3          A              4               3
            26      3          A              5               1
            27      3          A              6               5
            28      3          A              7               2
            29      3          B              2               0
            30      3          B              0               6
            31      3          B              2               3
            32      3          B              3               7
            33      3          C              7               0
            34      3          C              5               3
            35      3          C              3               2
            36      3          C              1               1
  

错误:ID值" _1"在同一个BY组中出现两次。

我可以使用LET语句来压制错误,但除了使日志混乱之外,SAS仅保留每个BY组的最后一次观察。

proc sort data = have out = sorted;
  by
    group
    replicate
  ;
run;

proc transpose data = sorted out = test;
  by
    group
    replicate
  ;
  var observation;
  id day;
run;

我不怀疑它是否可以采取一些克服方式,例如将每个组拆分为单独的数据集然后重新合并它们。看起来应该可以使用PROC TRANSPOSE,尽管如何让我感到惊讶。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

不确定你在谈论" SAS的痴迷......",但这里的问题相当简单;你需要告诉SAS四行(或其他)是独立的,不同的行。 by告诉SAS行级别ID是什么,但当您说by group replicate时,您会对其说谎,因为在此之下仍有多行。所以你需要一把独特的钥匙。 (在任何类似数据库的语言中都是如此,这里SAS没有什么独特之处。)

我会这样做 - 制作一个day_row字段,然后按此排序。

data have_id;
  set have;
  by group replicate day;
  if first.day then day_row = 0;
  day_row+1;
run;

proc sort data=have_id;
  by group replicate day_row;
run;
proc transpose data=have_id out=want(drop=_name_) prefix=observation_day_;
  by group replicate day_row;
  var observation;
  id day;
run;

答案 1 :(得分:1)

您的输出看起来不想转置数据,而只是想将其拆分为DAY1和DAY2设置并将它们合并在一起。这将按照它们出现的顺序将每个BY组的多个读数配对,这就像您在示例中所做的那样。

data want ;
  merge
    have(where=(day=1) rename=(observation=day_1))
    have(where=(day=2) rename=(observation=day_2))
  ;
  by group replicate;
  drop day ;
run;

您可以根据需要为DAY的值数量多次读取源数据。

如果您认为每个DAY的每个BY组可能没有相同数量的观察值,那么您应该在数据步骤结束时添加这些语句。

output;
call missing(of day_:);