dcast 中的 value.var 可以是一个列表还是有多个值变量?
Posted
技术标签:
【中文标题】dcast 中的 value.var 可以是一个列表还是有多个值变量?【英文标题】:can the value.var in dcast be a list or have multiple value variables? 【发布时间】:2014-05-28 04:34:41 【问题描述】:在dcast.data.table
的帮助文件中,有一条说明已经实现了一项新功能:“dcast.data.table 允许 value.var 列属于列表类型”
我认为这意味着一个列表中可以有多个值变量,即采用以下格式:
dcast.data.table(dt, x1~x2, value.var=list('var1','var2','var3'))
但是我们得到一个错误:'value.var' must be a character vector of length 1.
是否有这样的功能,如果没有,还有其他单线替代方案吗?
编辑:回复下面的 cmets
在某些情况下,您希望将多个变量视为value.var
。例如,假设 x2 包含 3 个不同的周,并且您有 2 个值变量,例如盐和糖的消耗量,并且您希望将这些变量转换为不同的周。当然,您可以将 2 个值变量“融合”到一列中,但是当您可以像 reshape
那样在一个函数中完成时,为什么还要使用两个函数呢?
(注意:我还注意到reshape
不能像dcast
那样将多个变量视为时间变量。)
所以我的意思是,我不明白为什么这些函数不允许在value.var
或time.var
中灵活地包含多个变量,就像我们允许id.var
中的多个变量一样。
【问题讨论】:
您误解了文档。 data.table 列可以是 list 类型,这样的列现在可以是value.var
列。
@Arun,我不完全确定这将是一个巨大的改进(或者我可能没有正确理解这个问题)。有多个value.var
s 的事实不是意味着数据没有完全“融化”吗?亚历克斯:您能否更新您的问题以跳出假设领域,并举例说明您可能想对这些多个value.var
s 做什么?也许你在想我在this answer 所做的事情?
@Arun 我已经详细说明了这篇文章的目的和我的询问。
相关问题:***.com/questions/27247078/…
相关:Convert data from long format to wide format with multiple measure columns
【参考方案1】:
更新
显然,the fix was much easier...
从技术上讲,您“显然没有这样的功能”的说法并不完全正确。 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
方法的一个可能优势是能够在同一步骤中进行聚合和重塑。
【讨论】:
感谢您抽出宝贵的时间阅读此内容。我不知道重铸似乎会融化+铸造。我想补充一点,reshape 包(但不是 reshape2)中的recast
是完整的,并且与您的 recast2 功能相同。
@AlexR,请在帖子顶部查看我的更新。显然,所需要的只是将recast
代码中的cast
更改为dcast
。【参考方案2】:
从 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
【讨论】:
【参考方案3】:使用来自A5C1D2H2I1M1N2O1R2T1's answer 的样本数据框mydf
。
使用 tidyr
编辑 2016 年 12 月
Reshape2 已替换为 tidyr package。
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
基于reshape2
的原始答案
@AlexR 添加到他的问题中:
当然,您可以将 2 个值变量“融合”成一列,
对于那些来这里根据reshape2 寻找答案的人,这里是如何融合数据然后基于“变量”使用 dcast。 .
dt2 <- melt(mydf, id = c("x1", "x2"))
变量列现在将包含“var1”、“var2”、“var3”。您可以使用
来达到预期的效果dt3 <- dcast(dt2, x1 ~ x2 + variable, value.var="value")
dt3
# 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
value.var 在此函数调用中是可选的,因为 dcast 会自动猜测它。
【讨论】:
2016 年 12 月的更新在我看来是目前最灵活的方法。 +1 现在gather
和spread
已被pivot_wider
和pivot_longer
在tidyr 中取代。以上是关于dcast 中的 value.var 可以是一个列表还是有多个值变量?的主要内容,如果未能解决你的问题,请参考以下文章
R语言学习笔记(十七):data.table包中melt与dcast函数的使用