【问题标题】:SAS - Split single column into two based value of non-binary ID columnSAS - 将单列拆分为两个基于非二进制 ID 列的值
【发布时间】:2017-07-11 16:39:26
【问题描述】:

我有如下数据:

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;

我想根据dayobservation分成两列。

                                        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

细心的 SO 读者会注意到我问了基本相同的问题 previously。但是,由于 SAS 对“级别”和“按组”的痴迷,由于用于拆分感兴趣变量的变量不是二元的,因此该解决方案无法推广。

直接尝试,出现以下情况:

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

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

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

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

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

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

              Obs    group    replicate      _NAME_       _1    _2

               1       1          A        observation     3     2
               2       1          B        observation     0     3
               3       1          C        observation     7     1
               4       2          A        observation     1     0
               5       2          B        observation     8     0
               6       2          C        observation     1     1
               7       3          A        observation     7     2
               8       3          B        observation     3     7
               9       3          C        observation     1     1

我不怀疑有一些笨拙的方法可以完成,例如将每个组分成一个单独的数据集,然后重新合并它们。看起来它应该可以用 PROC TRANSPOSE 来实现,尽管我怎么也想不通。有什么想法吗?

【问题讨论】:

    标签: sas


    【解决方案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;
    

    【讨论】:

    • 我想总是让我感到困惑的部分是,在某些情况下,BY 或 CLASS 语句的行为类似于或类似于主键。一如既往,您的回复很有启发性和赞赏。
    【解决方案2】:

    您的输出看起来不想转置数据,而只想将其拆分为 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 的值数量,您可以根据需要多次读取源数据。

    如果您认为每个 BY 组每天的观察次数可能不同,那么您应该在数据步骤的末尾添加这些语句。

    output;
    call missing(of day_:);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 2015-07-11
      • 2021-05-02
      • 1970-01-01
      • 2014-09-09
      • 2021-10-26
      相关资源
      最近更新 更多