我有一个像这样的data.table:
library(data.table)
dt <- data.table(a = c(rep("A", 3), rep("B", 3)), b = c(1, 3, 5, 2, 4, 6))
我需要对每个a
的值执行操作(预测),所以我决定将它们放在一个列表中,如下所示:
dt <- dt[, x := .(list(b)), by = a][, .SD[1,], by = a, .SDcols = "x"]
现在我想“融化”(这是我想到的事情)dt
回到原来的形式。
我可以在a
这样的极少数级别执行此操作:
dt2 <- rbind(expand.grid(dt[1, a], dt[1, x[[1]]]), expand.grid(dt[2, a], dt[2, x[[1]]]))
但当然,对于更多级别的a
,该解决方案是不切实际的。
我试过
dt2 <- dt[, expand.grid(a, x[[1]]), by = a]
导致
dt2
## a Var1 Var2
## 1: A A 1
## 2: A A 3
## 3: A A 5
## 4: B A 2
## 5: B A 4
## 6: B A 6
有趣的是,Var1
实际上并没有遵循预期的“A - B”模式(但至少a
仍然存在)。
有没有更好的方法来实现这一目标?
预期输出将是
的结果dt2[, .(a, Var2)]
答案 0 :(得分:3)
您正在寻找一种方法nest
(将列从原子矢量类型转换为列表类型)和unnest
(相反方向)以data.table方式。这不同于重新整形数据,其中spread
列值与行标题(dcast
)或gather
行标题为列值(melt
):
在data.table语法中,您可以在目标列上使用list
和unlist
来汇总或广播它以及组变量:
说我们是否从以下开始:
dt
# a b
# 1: A 1
# 2: A 3
# 3: A 5
# 4: B 2
# 5: B 4
# 6: B 6
要重复您在第一步中取得的成就,即nest
列b
,您可以这样做:
dt_nest <- dt[, .(b = list(b)), a]
dt_nest
# a b
# 1: A 1,3,5
# 2: B 2,4,6
要反方向,请将unlist
与组变量一起使用:
dt_nest[, .(b = unlist(b)), a]
# a b
# 1: A 1
# 2: A 3
# 3: A 5
# 4: B 2
# 5: B 4
# 6: B 6