【问题标题】:how can i melt a data.table with concatenated column names我怎样才能融化带有连接列名的data.table
【发布时间】:2014-07-31 18:56:32
【问题描述】:

我正在使用 dcast.data.table 将长 data.table 转换为宽 data.table

library(data.table)
library(reshape2)

set.seed(1234)
dt.base <- data.table(A = rep(c(1:3),2), B = rep(c(1:2),3), C=c(1:4,1,2),thevalue=rnorm(6))


#from long to wide using dcast.data.table()
dt.cast <- dcast.data.table(dt.base, A ~ B + C, value.var = "thevalue", fun = sum)

#now some stuff happens e.g., please do not bother what happens between dcast and melt
setkey(dt.cast, A)
dt.cast[2, c(2,3,4):=1,with = FALSE]

现在我想将 data.table 再次融化回原来的列布局,在这里我被卡住了,如何将连接的 columnames 与强制转换的 data.table 分开,这是我的问题

dt.melt <- melt(dt.cast,id.vars = c("A"), value.name = "thevalue")

我需要两列而不是一列

我正在寻找的结果可以用这段代码产生

#update
dt.base[A==2 & B == 1 & C == 1, thevalue :=1]
dt.base[A==2 & B == 2 & C == 2, thevalue :=1]

#insert (2,1,3 was not there in the base data.table)
dt.newrow <- data.table(A=2, B=1, C=3, thevalue = 1)
dt.base <-rbindlist(list(dt.base, dt.newrow))
dt.base

一如既往地感谢任何帮助

【问题讨论】:

  • 不清楚您希望最终结果是什么样子。您能否显示所需的输出。想必,你不能只拼接dt.meltvariable列吗?
  • @RicardoSaporta 我添加了一些额外的代码,以产生我正在寻找的结果。但与此同时,大卫有一个很好的解决方案,现在我只是在徘徊,如果这可以直接从 melt-function 中实现

标签: r data.table


【解决方案1】:

这对你有用吗?

colnames <- c("B", "C")
dt.melt[, (colnames) := (colsplit(variable, "_", colnames))][, variable := NULL]
subset(dt.melt, thevalue != 0)
# or dt.melt[thevalue != 0, ]

#   A   thevalue B C
#1: 1 -1.2070657 1 1
#2: 2  1.0000000 1 1
#3: 2  1.0000000 1 3
#4: 3  1.0844412 1 3
#5: 2  1.0000000 2 2
#6: 3  0.5060559 2 2
#7: 1 -2.3456977 2 4

如果您的数据集不可表示并且有效行中可能有零,这里是替代方法

colnames <- c("B", "C")
setkey(dt.melt[, (colnames) := (colsplit(variable, "_",colnames))][, variable := NULL], A, B, C)
setkey(dt.base, A, B, C)
dt.base <- dt.melt[rbind(dt.base, data.table(A = 2, B = 1, C = 3), fill = T)]
dt.base[, thevalue.1 := NULL]

##    A B C   thevalue
## 1: 1 1 1 -1.2070657
## 2: 1 2 4 -2.3456977
## 3: 2 1 1  1.0000000
## 4: 2 2 2  1.0000000
## 5: 3 1 3  1.0844412
## 6: 3 2 2  0.5060559
## 7: 2 1 3  1.0000000

编辑

作为。 @Arun 建议,最有效的方法是使用 @AnandaMahto cSplit 函数,因为它也在使用 data.table,即,

cSplit(dt.melt, "variable", "_")

二次编辑

为了节省手动合并,您可以在 dcasting 时设置fill = NA(例如),然后使用csplit 一次性完成所有操作,例如

dt.cast <- dcast.data.table(dt.base, A ~ B + C, value.var = "thevalue", fun = sum, fill = NA)
setkey(dt.cast, A)
dt.cast[2, c(2,3,4):=1,with = FALSE]
dt.melt <- melt(dt.cast,id.vars = c("A"), value.name = "thevalue")
dt.cast <- cSplit(dt.melt, "variable", "_")[!is.na(thevalue)]
setnames(dt.cast, 3:4, c("B","C"))

#    A   thevalue B C
# 1: 1 -1.2070657 1 1
# 2: 2  1.0000000 1 1
# 3: 2  1.0000000 1 3
# 4: 3  1.0844412 1 3
# 5: 2  1.0000000 2 2
# 6: 3  0.5060559 2 2
# 7: 1 -2.3456977 2 4

【讨论】:

  • 嘿大卫,这正是我正在寻找的,太好了,我必须检查它的扩展方式,我再次意识到我对几分钟前所做的事情有偏见......使用 dcast 让我觉得我必须使用融化,有趣!如果在接受您的答案之前有“本机”融化答案,我将等待几个小时
  • 很遗憾,colsplit 无法很好地扩展。尝试改用unlist(strsplit(x, "_"))
  • 试试@AnandaMahto 的cSplit 函数。你可以得到它here
  • @Arun,你是对的。想知道我怎么没有想到它,因为它已经在我的机器上采购了......
  • @TomMartens,查看我上次编辑重新设置fill = NA 和使用cSplit。我认为这是最好的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2020-09-24
  • 1970-01-01
相关资源
最近更新 更多