将 melt 与 data.table 一起使用仅适用于多个测量变量

Using melt with data.table only works with multiple measure variables

我对 data.table::melt() 的行为感到困惑。

我想将 data.table 从宽变长,

这是我的 data.table:

dt <- data.table(id=c(1,2,3), varA1=c(2,6,1), varA2=c(1,1,1),varA3=c(1,2,3),  
                              varB1=c(1,0,1), varB2=c(1,1,1),varB3=c(0,0,0))

这是我想要的:

  id index varA
1:  1     1    2
2:  2     1    6
3:  3     1    1 
4:  1     2    1
5:  2     2    1
6:  3     2    1
7:  1     3    1
8:  2     3    2
9:  3     3    3

如果我同时包含 varAvarB 作为我的度量变量,它工作正常,使用:

dt_long <- melt(dt, id.vars = "id", measure=patterns("^varA","^varB"), value.name = c("varA","varB"),variable.name = "index")

输出符合预期:

   id index varA varB
1:  1     1    2    1
2:  2     1    6    0
3:  3     1    1    1
4:  1     2    1    1
5:  2     2    1    1
6:  3     2    1    1
7:  1     3    1    0
8:  2     3    2    0
9:  3     3    3    0

不过,我只要varA。只有一个测量变量,它不再有效。使用

dt_long <- melt(dt, id.vars ="id", measure=patterns("^varA"), value.name = "varA",variable.name = "index")

我得到:

   id index varA
1:  1 varA1    2
2:  2 varA1    6
3:  3 varA1    1
4:  1 varA2    1
5:  2 varA2    1
6:  3 varA2    1
7:  1 varA3    1
8:  2 varA3    2
9:  3 varA3    3

为什么这里的 index 变量没有像以前那样列出 1,2,3?

melt measure.vars 中使用多个列很棘手。

来自 melt 有关 measure.vars 的帮助:

multiple patterns will produce multiple columns

如果我们使用 "^varA","^varB"data.table:::patterns 源代码应用到 dt,我们得到:

cols <- colnames(dt)
p = unlist(list("^varA","^varB"), use.names = any(nzchar(list("^varA","^varB"))))
lapply(p, grep, cols)

[[1]]
[1] 2 3 4

[[2]]
[1] 5 6 7

导致:

  • VarA1 关联 VarB1,因子指数 = 1
  • VarA2 关联 VarB2,因子指数 = 2
  • VarA3 关联 VarB3,因子指数 = 3

请注意,索引编号与 VarXi 索引无关,它只是 VarAi-VarBi 因子的自动编号。

例如,如果我们删除 VarA1,我们会得到以下结果:

   id index varA varB
1:  1     1    1    1
2:  2     1    1    0
3:  3     1    1    1
4:  1     2    1    1
5:  2     2    2    1
6:  3     2    3    1
7:  1     3   NA    0
8:  2     3   NA    0
9:  3     3   NA    0
  • VarA2 关联 VarB1,因子指数 = 1
  • VarA3VarB2 关联,因子指数 = 2
  • VarB3单独,因子指数=3

在这两种情况下,由于这个因素是一个复合因素,data.table returns 它的 numeric 索引。

只用一个pattern时,直接得到一个levels对应这个单pattern的因子:

dt_long <- melt(dt, id.vars = "id", measure=patterns("^varA"), value.name = c("varA"),variable.name = "index")[]
dt_long$index
[1] varA1 varA1 varA1 varA2 varA2 varA2 varA3 varA3 varA3
Levels: varA1 varA2 varA3

您可以将其转换为 numeric 以获得预期结果:

dt_long[,index :=as.numeric(index)][]
   id index varA
1:  1     1    2
2:  2     1    6
3:  3     1    1
4:  1     2    1
5:  2     2    1
6:  3     2    1
7:  1     3    1
8:  2     3    2
9:  3     3    3