【问题标题】:long vs wide, tidy vs efficient长与宽,整洁与高效
【发布时间】:2017-04-19 07:20:28
【问题描述】:

在我当前的数据分析工作流程中,在长格式和宽格式之间切换时,我发现了一些次优步骤。考虑下面显示的三个迹线,它们具有常见的x 值,

我的数据是长格式的,可​​用于绘图和各种 pipy 事物,但对于分析的某些部分,处理宽(类似矩阵)格式似乎更容易。例如,在这个虚拟示例中,我可能希望将所有迹线的基线设置为 0,方法是减去 0 到 0.25 之间的每个迹线的平均值(灰色阴影区域)。

我找不到一种简单的方法来做这种长格式的事情。

我目前的策略是切换回宽格式,但 i) 我不记得 dcast/reshape 的正确语法,ii) 在两者之间来回切换效率很低。

dwide <- reshape2::dcast(dlong, x~..., value.var="y")
dwide[,-1] <- sweep(dwide[,-1], 2, colMeans(dwide[dwide$x < 0.25, -1]), FUN="-")
dlong2 <- melt(dwide, id="x")

我是否错过了一些可以提供帮助的工具?我愿意接受 data.table 建议。


完整的可重现示例:

library(ggplot2)
library(plyr)
library(reshape2)

## dummy data as noisy lorentzian-shaped peaks with random offset

set.seed(1234)
fake_data <- function(a, x = seq(0, 1, length=100)){ 
  data.frame(x = x, 
             y = jitter(1e-3 / ((x - a)^2 + 1e-3) + runif(1,0,1), 
                   amount = 0.1))
}

## apply function to all combinations of parameters (one here)
dlong <- plyr::mdply(data.frame(a = c(0.4,0.5,0.6)), fake_data)

ggplot(dlong, aes(x, y, colour=factor(a))) + geom_line() +
  annotate("rect", xmin=-Inf, xmax=0.25, ymin=-Inf, ymax=Inf, fill="grey", alpha = 0.3) +
  theme_minimal()

dwide <- reshape2::dcast(dlong, x~..., value.var="y")
str(dwide)

dwide[,-1] <- sweep(dwide[,-1], 2, colMeans(dwide[dwide$x < 0.25, -1]), FUN="-")
dlong2 <- melt(dwide, id="x")

ggplot(dlong2, aes(x, value, colour=variable)) + geom_line()  +
  theme_minimal()

【问题讨论】:

  • 我发现tidyrgatherspreadreshape2 需要更少的思考,除了spread 对索引可能非常挑剔。在这里,dwide &lt;- dlong %&gt;% spread(a, y)dlong2 &lt;- dwide %&gt;% gather(variable, value, -x)(或使用 ay 代替 variablevalue 以保留原始名称)。
  • 我同意,它们看起来确实更直观。我会尝试更多地使用它们

标签: r tidyverse


【解决方案1】:

也许您的最小示例太微不足道,无法捕捉到您可能想要从长到宽再到长的所有情况。但至少对于您的示例,我通常会使用 data.table 进行此类操作:

setDT(dlong)[, y2 := y - mean(y[x < 0.25]), by=a]

ggplot(dlong, aes(x, y2, colour=factor(a))) + 
  geom_line() +
  theme_minimal()

分解:

  • by = a 对数据进行分组,以便 [.data.table 的第二个参数中的操作应用于与 a 的每个值对应的 dlong 子集

  • y2 := y - mean(y[x &lt; 0.25]) 因此是针对 a 的每个值单独计算的

  • := 是 data.table 中的一个特殊运算符,它提供引用赋值而不是复制赋值(非常有效)

  • [.datat.table 的第一个参数在这里留空,因为我们希望对原始 dlong 数据的所有行进行操作。

dplyr by

几乎可以做到同样的事情
dlong %>% 
  group_by(a) %>% 
  mutate(y2 = y - mean(y[x < 0.25]))

【讨论】:

  • 谢谢,这听起来很有希望。我不使用 data.table,所以语法对我来说有点陌生。你说得对,这个例子可能有点太少了......我会看看我是否可以提出更有说服力的东西。
  • 在 dplyr 中:dlong %&gt;% group_by(a) %&gt;% mutate(y2 = y - mean(y[x &lt; 0.25])) %&gt;% ggplot(aes(x, y2, colour = factor(a))) + geom_line() + theme_minimal()
猜你喜欢
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
相关资源
最近更新 更多