R:将多列转换为单列

时间:2016-06-10 20:07:18

标签: r

我有一个看起来像这样的数据框

+---------+--------+--------+--------+-------+
|   ID    | week1_t| week1_a| week2_t|week2_a|
+---------+--------+--------+--------+-------+
|    1    | 12     | 22     |  17    |   4   |
|    1    | 15     | 32     |  18    |   5   |
|    1    | 24     | 12     |  29    |   6   |
|    2    | 45     | 11     |  19    |   8   |
|    2    | 23     | 33     |  20    |   10  |
+---------+--------+--------+--------+-------+

有48列(第1周至第24周),后缀为“t”和“a”。我想将所有周列整合到一个“周”列中,如下所示:

+---------+--------+--------+--------
|   ID    | week   |  t     |  a    |
+---------+--------+--------+--------
|    1    | 1     | 22      |  17   |
|    1    | 2     | 32      |  18   |
|    1    | 3     | 12      |  19   | 
|    1    | 5     | 33      |  20   | 
+---------+--------+--------+-------

如何在R中进行此转换?我无法想到在多个if语句和for循环之外执行此操作的方法。

数据

dd <- read.table(header = TRUE, text = "ID week1_t week1_a  week2_t week2_a
  1      12      22       17       4   
  1      15      32       18       5   
  1      24      12       29       6   
  2      45      11       19       8   
  2      23      33       20      10")

2 个答案:

答案 0 :(得分:3)

您可以使用data.table melt

library(data.table)
setDT(dd)
melt(dd, id = 1, measure=patterns("_t$", "_a$"), value.name = c("t", "a"), 
     variable.name = "week")

    ID week  t  a
 1:  1    1 12 22
 2:  1    1 15 32
 3:  1    1 24 12
 4:  2    1 45 11
 5:  2    1 23 33
 6:  1    2 17  4
 7:  1    2 18  5
 8:  1    2 29  6
 9:  2    2 19  8
10:  2    2 20 10

您可以阅读?melt

  

measure.vars现在也接受一个字符/整数向量列表   熔化成多个柱 - 即熔化成多于一个值   列同时。使用函数模式提供多个   图案很方便。参见示例部分

答案 1 :(得分:0)

使用tidyr / dplyr

library(dplyr)
library(tidyr)

       # add row index so later spreading indexed correctly
dd %>% add_rownames() %>% 
    # melt to long format
    gather(week, value, -ID, -rowname) %>% 
    # separate week number from variable suffix
    separate(week, c('week', 'var')) %>% 
    # reduce week number to actual number
    mutate(week = extract_numeric(week)) %>% 
    # spread a and t values back to wide form
    spread(var, value) %>% 
    # clean up
    select(-rowname)

# Source: local data frame [10 x 4]
# 
#       ID  week     a     t
#    (int) (dbl) (int) (int)
# 1      1     1    22    12
# 2      1     2     4    17
# 3      1     1    32    15
# 4      1     2     5    18
# 5      1     1    12    24
# 6      1     2     6    29
# 7      2     1    11    45
# 8      2     2     8    19
# 9      2     1    33    23
# 10     2     2    10    20