有没有办法在 tbl 中使用重塑?
Is there a way to use reshape in tbl?
在上一个问题中,我在使用 reshape 时遇到了问题:
reshape error - invalid 'row.names' length
几小时后我意识到这是因为我使用的是 tbl 格式而不是 data.frame。所以要使用重塑并保持我必须做的 tbl 环境:
mydata %>% as.data.frame %>% reshape(, ...) %>% as.tbl
所以我想知道是否有其他方法。
比任何其他原因都更有答案,这里有四个选项可供考虑。
首先,如果您想将 reshape
与 "dplyr" 一起使用,您必须使用 reshape
中的 new.row.names
参数,并设置它们到您希望重塑数据集具有的行数的序列。计算很容易。取一批从宽格式到长格式的列的长度,并将其乘以原始数据集中的行数。
这种方法肯定会让 Hadley 感到不快,所以使用风险自负。
mydf <- tbl_df(mydf)
class(mydf)
# [1] "tbl_df" "tbl" "data.frame"
mydf %>%
reshape(
idvar="g_id",
direction="long",
varying=list(c(5:14),c(15:24)),
v.names=c("PLC","P"),
new.row.names = seq_len(length(5:14) * nrow(mydf)))
另一种可能使 Hadley 不安但稍微不那么紧张的方法是使用 melt
,但是 "data.table" 中的 melt
,而不是 "reshape2" .当然,这需要您将 tbl_df
转换为 data.table
,因此与您当前的方法类似,它需要另一个步骤。
library(data.table)
mydf %>%
data.table %>%
melt(measure.vars = patterns("PLC[0-9]+", "P[0-9]+"),
value.name = c("PLC", "P"))
留在 Hadleyverse 内,您可以尝试 "tidyr"(如@DavidArenburg 所建议)。它并不像他想象的那么漂亮,因为它需要首先制作一个 非常 长的数据集,然后 re-widening 它,这与上面的 melt
方法不同一步完成 not-so-long 重塑。
library(tidyr)
mydf %>%
gather(var, val, starts_with("P")) %>%
mutate(var = gsub("([A-Z]+)", "\1_", var)) %>% ## you can probably be clever and...
separate(var, into = c("variable", "time")) %>% ## come up with some fancier regex
spread(variable, val)
最后,还有 merged.stack
来自我的 "splitstackshape" 包裹。有了它,方法就像:
library(splitstackshape)
merged.stack(mydf, var.stubs = c("PLC", "P"), sep = "var.stubs")
在上一个问题中,我在使用 reshape 时遇到了问题:
reshape error - invalid 'row.names' length
几小时后我意识到这是因为我使用的是 tbl 格式而不是 data.frame。所以要使用重塑并保持我必须做的 tbl 环境:
mydata %>% as.data.frame %>% reshape(, ...) %>% as.tbl
所以我想知道是否有其他方法。
比任何其他原因都更有答案,这里有四个选项可供考虑。
首先,如果您想将 reshape
与 "dplyr" 一起使用,您必须使用 reshape
中的 new.row.names
参数,并设置它们到您希望重塑数据集具有的行数的序列。计算很容易。取一批从宽格式到长格式的列的长度,并将其乘以原始数据集中的行数。
这种方法肯定会让 Hadley 感到不快,所以使用风险自负。
mydf <- tbl_df(mydf)
class(mydf)
# [1] "tbl_df" "tbl" "data.frame"
mydf %>%
reshape(
idvar="g_id",
direction="long",
varying=list(c(5:14),c(15:24)),
v.names=c("PLC","P"),
new.row.names = seq_len(length(5:14) * nrow(mydf)))
另一种可能使 Hadley 不安但稍微不那么紧张的方法是使用 melt
,但是 "data.table" 中的 melt
,而不是 "reshape2" .当然,这需要您将 tbl_df
转换为 data.table
,因此与您当前的方法类似,它需要另一个步骤。
library(data.table)
mydf %>%
data.table %>%
melt(measure.vars = patterns("PLC[0-9]+", "P[0-9]+"),
value.name = c("PLC", "P"))
留在 Hadleyverse 内,您可以尝试 "tidyr"(如@DavidArenburg 所建议)。它并不像他想象的那么漂亮,因为它需要首先制作一个 非常 长的数据集,然后 re-widening 它,这与上面的 melt
方法不同一步完成 not-so-long 重塑。
library(tidyr)
mydf %>%
gather(var, val, starts_with("P")) %>%
mutate(var = gsub("([A-Z]+)", "\1_", var)) %>% ## you can probably be clever and...
separate(var, into = c("variable", "time")) %>% ## come up with some fancier regex
spread(variable, val)
最后,还有 merged.stack
来自我的 "splitstackshape" 包裹。有了它,方法就像:
library(splitstackshape)
merged.stack(mydf, var.stubs = c("PLC", "P"), sep = "var.stubs")