如何将面板数据转换为特定的宽格式?

时间:2018-12-20 22:16:15

标签: r data.table reshape

我有一个像这样的长格式数据框

> df2
   id t treat    value
1   1 1     0 5.718226
2   1 2     1 5.954669
3   1 3     0 4.485165
4   2 1     1 6.616181
5   2 2     0 4.521301
6   2 3     1 6.955451
7   3 1     0 3.851682
8   3 2     1 6.907178
9   3 3     1 6.274501
10  4 1     1 6.092860
11  4 2     0 4.327431
12  4 3     0 6.019627

我想要宽格式的输出:

  id treat.1  value.1 treat.2  value.2 treat.3  value.3
1  1       0 5.718226       1 5.954669       0 4.485165
2  2       1 6.616181       0 4.521301       1 6.955451
3  3       0 3.851682       1 6.907178       1 6.274501
4  4       1 6.092860       0 4.327431       0 6.019627

我只能这样做:

l2.2 <- with(df2, split(df2, t))
l2.3 <- lapply(seq_along(l2.2), function(x) {
  names(l2.2[[x]])[3:4] <- paste0(names(l2.2[[x]])[3:4], ".", names(l2.2)[x])
  l2.2[[x]][-2]
})

Reduce(function(x, y) 
  merge(x, y, all=TRUE, by=intersect(names(x), names(y))), l2.3)

对我来说,这似乎太复杂了,但是我无法简化它。我想学习如何使用reshape()aggregate()data.table::dcast()执行此操作。我接近了,但我无法弄清楚到底是什么:

重塑:

df2.1 <- reshape(df2, timevar="t", idvar=c("id", "treat"), direction="wide")
df2.2 <- reshape(df2.1, timevar="treat", idvar="id", direction="wide")
> df2.2[, c(1, 2, 5, 3, 6, 4, 7)]
   id value.1.0 value.1.1 value.2.0 value.2.1 value.3.0 value.3.1
1   1  5.718226        NA        NA  5.954669  4.485165        NA
4   2        NA  6.616181  4.521301        NA        NA  6.955451
7   3  3.851682        NA        NA  6.907178        NA  6.274501
10  4        NA  6.092860  4.327431        NA  6.019627        NA

data.table:

> data.table::dcast(df2, id + treat ~ t)
  id treat        1        2        3
1  1     0 5.718226       NA 4.485165
2  1     1       NA 5.954669       NA
3  2     0       NA 4.521301       NA
4  2     1 6.616181       NA 6.955451
5  3     0 3.851682       NA       NA
6  3     1       NA 6.907178 6.274501
7  4     0       NA 4.327431 6.019627
8  4     1 6.092860       NA       NA

我也尝试了aggregate()次失败。

有人可以告诉我如何在基数R和data.table::dcast()中执行此操作吗?

编辑:

与这个简单的示例相反,我在数据中还有其他一些id和随时间变化的变量,请参见下面的数据中的df3

@markus的reshape()解决方案有效时,dcast()引发错误:

> reshape(df3, timevar="t", idvar=c("id.1", "id.2"), direction="wide")
   id.1 id.2 treat.1 value.1.1  value.2.1 treat.2 value.1.2  value.2.2 treat.3 value.1.3  value.2.3
1     1    1       0  5.718226  0.4297986       1  5.954669 -1.4007124       0  4.485165 -1.1741134
4     2    1       1  6.616181 -1.0516253       0  4.521301  1.5686463       1  6.955451 -0.4306961
7     3    2       0  3.851682 -0.3046341       1  6.907178 -0.6669521       1  6.274501 -0.2582921
10    4    2       1  6.092860  1.3231503       0  4.327431  1.6899552       0  6.019627 -0.4263450

> dcast(df3, id ~ t, value.var = c("treat", "value"))
Error in .subset2(x, i, exact = exact) : subscript out of bounds
In addition: Warning message:
In if (!(value.var %in% names(data))) { :
  the condition has length > 1 and only the first element will be used

数据:

df2 <- structure(list(id = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L),
                      t = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3),
                      treat = c(0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0),
                      value = c(5.7182263351077, 5.95466888906233,
                                4.48516458093838, 6.61618146498587,
                                4.52130082895974, 6.95545080306353,
                                3.85168235272874, 6.90717809069993,
                                6.27450118041287, 6.09285968998526,
                                4.32743136605772, 6.01962658742754)),
                 row.names = c(NA, -12L), class = "data.frame")

df3 <- structure(list(id.1 = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), 
                      id.2 = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), 
                      t = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3), 
                      treat = c(0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0), 
                      value.1 = c(5.7182263351077, 5.95466888906233, 4.48516458093838, 
                                  6.61618146498587, 4.52130082895974, 6.95545080306353, 
                                  3.85168235272874, 6.90717809069993, 6.27450118041287, 
                                  6.09285968998526, 4.32743136605772, 6.01962658742754), 
                      value.2 = c(0.429798618225556, -1.40071244216677, -1.17411337999421, 
                                  -1.05162530600877, 1.56864628901013, -0.430696055983823, 
                                  -0.304634116536374, -0.666952117966313, -0.258292124936937, 
                                  1.32315028276158, 1.68995518578212, -0.426345031174389)), 
                 class = "data.frame", row.names = c(NA, -12L))

1 个答案:

答案 0 :(得分:4)

使用dcast中的data.table,您需要将列treatvalue指定为value.var

library(data.table)
setDT(df2)
dcast(df2, id ~ t, value.var = c("treat", "value"))
#   id treat_1 treat_2 treat_3  value_1  value_2  value_3
#1:  1       0       1       0 5.718226 5.954669 4.485165
#2:  2       1       0       1 6.616181 4.521301 6.955451
#3:  3       0       1       1 3.851682 6.907178 6.274501
#4:  4       1       0       0 6.092860 4.327431 6.019627

reshape将以这种方式工作

reshape(df2, idvar = "id", timevar = "t", direction = "wide")
#   id treat.1  value.1 treat.2  value.2 treat.3  value.3
#1   1       0 5.718226       1 5.954669       0 4.485165
#4   2       1 6.616181       0 4.521301       1 6.955451
#7   3       0 3.851682       1 6.907178       1 6.274501
#10  4       1 6.092860       0 4.327431       0 6.019627