【问题标题】:Converting code from ddply to plyr in R在 R 中将代码从 ddply 转换为 plyr
【发布时间】:2016-01-09 20:46:48
【问题描述】:

我想更改一些代码以使用 plyr 而不是 ddply,因为我认为它在我的大型 (>1e6) 数据集上会更快。这是一个示例数据集:

ID <- rep(1:3, each=6)
Row <- rep(1, each=18) 
Col <- rep(rep(1:2, each=3), times=3)
Meas <- rnorm(18,3,1)
len <- rep(1:3, times=6)

df <- data.frame(ID, Row, Col, Meas, len)

我通常使用的代码是这样的:

res <- ddply(df, c("ID", "Row", "Col"), function(x) coefficients(lm(Meas~len,x)))

它对 df 的每个子集按 ID、Row 和 Col 执行 Meas 对 len 的 lm,提取系数。在我的大型数据集上,它需要 30 秒(我知道,这不是世界末日)。当我尝试 plyr 时:

res2 <- df %>% group_by("ID", "Row", "Col") %>% (function(x) coefficients(lm(Meas~len,x))) %>%
  as.data.frame()

我只得到一个拦截和毕业。我读过这篇文章 (extracting p values from multiple linear regression (lm) inside of a ddply function using spatial data),它给了我这个尝试:

res3 <- df %>% group_by("ID", "Row", "Col") %>%
  do({model=lm(Meas~len, data=.)
  data.frame(tidy(model),
             glance(model))})

但还是没有运气。我确定我错过了一些简单的东西。

更新:

出于对在大型数据集上运行类似事情的任何人的兴趣:

system.time(
lres <- ddply(I, c("ERF", "Wafer", "Row", "Col"), function(x) coefficients(lm(Rds.on.fwd~Length,x)))
)

user  system elapsed 
  25.80    0.06   26.02

system.time(
  lres2 <- I %>% group_by(ERF, Wafer, Row, Col) %>% do(
    as.data.frame.list(coef(lm(Rds.on.fwd~Length, data=.))))
  )

user  system elapsed 
  43.12    0.25   44.02 

system.time(
lres3 <- setDT(I)[, as.list(coef(lm(Rds.on.fwd~Length))), .(ERF,Wafer, Row, Col)]
)

user  system elapsed 
  19.77    0.05   19.91

所以实际上@akrun data.table 选项是最好的,所以再次感谢你。

【问题讨论】:

  • df %&gt;% group_by(ID, Row, Col) %&gt;% do(as.data.frame.list(coef(lm(Meas~len, data=.))))
  • 可爱,谢谢。那么我可以确认一下“do”的作用以及为什么需要“.list”。
  • 其实google会告诉我,不用担心。再次感谢。
  • 还可以查看broom 包。这可以为您从lm提取相关信息。
  • 对于未来的读者,我想指出不要错过 plyr 版本中去掉引号的重要性。它们没有被用作字符串。

标签: r plyr


【解决方案1】:

我们修改 OP 的最后一段代码以获得预期的输出。我们使用变量'Meas'和'len'按变量'ID'、'Row'和'Col'、dolm分组,用coef提取系数,将其转换为list然后到data.frame (as.data.frame.list) 创建两个新列('intercept' 和 'slope')。

df %>% 
  group_by(ID, Row, Col) %>%
  do(as.data.frame.list(coef(lm(Meas~len, data=.))))

或者使用data.table,我们将“data.frame”转换为“data.table”,按“ID”、“Row”和“Col”分组,执行lm,提取系数,然后转换到list 以便我们得到两个新列。

library(data.table)
setDT(df)[, as.list(coef(lm(Meas~len))), .(ID, Row, Col)]

【讨论】:

  • 这是一个答案,但它接近于仅代码的答案。最好解释一下答案。
  • @Elin 添加了一些文字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
相关资源
最近更新 更多