将代码从ddply转换为R中的plyr

时间:2015-10-12 11:29:39

标签: r plyr

我想改变我的一些代码来使用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)))

它通过ID,Row和Col为df的每个子集执行一次lm for Meas,并提取系数。在我的大数据集上需要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选项是最好的,所以再次感谢你。

1 个答案:

答案 0 :(得分:3)

我们修改OP的最后一段代码以获得预期的输出。我们根据变量&#39; ID&#39;,&#39; Row&#39;和&#39; Col&#39;,do lm使用变量&#39; Meas&#39;和&#39; len&#39;,用coef提取系数,将其转换为list,然后转换为data.frameas.data.frame.list)以创建两个新列( &#39;拦截&#39;和&#39;斜坡&#39;)。

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

或者使用data.table,我们会转换&#39; data.frame&#39;到&#39; data.table,按&#39; ID&#39;,&#39; Row&#39;和&#39; Col&#39;,执行lm,提取系数,并转换为list,以便我们获得两个新列。

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