在dcast.data.table
的帮助文件中,有一条说明已实现新功能的说明:&#34; dcast.data.table允许value.var列为类型列表&#34; < / p>
我认为这意味着列表中可以有多个值变量,即采用以下格式:
dcast.data.table(dt, x1~x2, value.var=list('var1','var2','var3'))
但我们收到错误:'value.var' must be a character vector of length 1.
是否有这样的功能,如果没有,那么其他单线替代品会是什么?
编辑:回复以下评论
在某些情况下,您要将多个变量视为value.var
。想象一下,例如x2由3个不同的周组成,你有2个值变量,如盐和糖的消耗,你想在不同的周内投射这些变量。当然,你可以融化&#39;将2个值变量放入一个列中,但为什么要使用两个函数做什么,当你可以在像reshape
这样的函数中做到这一点时呢?
(注意:我还注意到reshape
无法将多个变量视为dcast
的时间变量。)
所以我的观点是,我不明白为什么这些功能不允许灵活地在value.var
或time.var
中包含多个变量,正如我们所允许的那样id.var
的多个变量。
答案 0 :(得分:35)
从data.table的v1.9.6开始,我们可以同时转换多个value.var
列(并在fun.aggregate
中使用多个聚合函数)。有关详情,请参阅?dcast
和Efficient reshaping using data.tables小插图。
以下是我们如何使用dcast
:
dcast(setDT(mydf), x1 ~ x2, value.var=c("salt", "sugar"))
# x1 salt_1 salt_2 salt_3 sugar_1 sugar_2 sugar_3
# 1: 1 3 4 6 1 2 2
# 2: 2 10 3 9 5 3 6
# 3: 3 10 7 7 4 6 7
答案 1 :(得分:10)
显然,the fix was much easier ......
从技术上讲,你的陈述表明“#34;显然没有这样的功能&#34;并非完全正确。 recast
函数中存在这样的特征(隐藏了熔化和铸造过程),但似乎Hadley忘记完成函数或其他东西:函数返回相关的list
部分操作。
这是一个最小的例子......
一些示例数据:
set.seed(1)
mydf <- data.frame(x1 = rep(1:3, each = 3),
x2 = rep(1:3, 3),
salt = sample(10, 9, TRUE),
sugar = sample(7, 9, TRUE))
mydf
# x1 x2 salt sugar
# 1 1 1 3 1
# 2 1 2 4 2
# 3 1 3 6 2
# 4 2 1 10 5
# 5 2 2 3 3
# 6 2 3 9 6
# 7 3 1 10 4
# 8 3 2 7 6
# 9 3 3 7 7
您似乎想要达到的效果:
reshape(mydf, idvar='x1', timevar='x2', direction='wide')
# x1 salt.1 sugar.1 salt.2 sugar.2 salt.3 sugar.3
# 1 1 3 1 4 2 6 2
# 4 2 10 5 3 3 9 6
# 7 3 10 4 7 6 7 7
recast
正在行动中。 (请注意,这些值都是我们所期望的维度中的所有值。)
library(reshape2)
out <- recast(mydf, x1 ~ x2 + variable, measure.var = c("salt", "sugar"))
### recast(mydf, x1 ~ x2 + variable, id.var = c("x1", "x2"))
out
# $data
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 3 1 4 2 6 2
# [2,] 10 5 3 3 9 6
# [3,] 10 4 7 6 7 7
#
# $labels
# $labels[[1]]
# x1
# 1 1
# 2 2
# 3 3
#
# $labels[[2]]
# x2 variable
# 1 1 salt
# 2 1 sugar
# 3 2 salt
# 4 2 sugar
# 5 3 salt
# 6 3 sugar
老实说,我不确定这是不完整的功能,还是它是另一个功能的辅助功能。
所有信息都可以将数据重新组合在一起,从而可以轻松编写如下函数:
recast2 <- function(...) {
inList <- recast(...)
setNames(cbind(inList[[2]][[1]], inList[[1]]),
c(names(inList[[2]][[1]]),
do.call(paste, c(rev(inList[[2]][[2]]), sep = "_"))))
}
recast2(mydf, x1 ~ x2 + variable, measure.var = c("salt", "sugar"))
# x1 salt_1 sugar_1 salt_2 sugar_2 salt_3 sugar_3
# 1 1 3 1 4 2 6 2
# 2 2 10 5 3 3 9 6
# 3 3 10 4 7 6 7 7
同样,recast2
方法的一个可能优势是能够在同一步骤中聚合和重塑。
答案 2 :(得分:8)
使用A5C1D2H2I1M1N2O1R2T1's answer中的示例数据框hamcrest
。
mydf
Reshape2已替换为tidyr package。
tidyr
library(tidyr)
mydf %>%
gather(variable, value, -x1, -x2) %>%
unite(x2_variable, x2, variable) %>%
spread(x2_variable, value)
# x1 1_salt 1_sugar 2_salt 2_sugar 3_salt 3_sugar
# 1 1 3 1 4 2 6 2
# 2 2 10 5 3 3 9 6
# 3 3 10 4 7 6 7 7
@AlexR加入了他的问题:
当然,您可以将2个值变量“融化”为一个列,
对于那些来这里寻找基于reshape2的答案的人来说,这里是如何融合数据然后根据“变量”使用dcast。
reshape2
变量列现在将包含'var1','var2','var3'。您可以使用
达到预期的效果dt2 <- melt(mydf, id = c("x1", "x2"))
value.var在此函数调用中是可选的,因为dcast会自动猜测它。