使用data.table将lm函数应用于不同的数据范围和单独的组

时间:2014-02-15 04:58:22

标签: r data.table plyr lm

如何使用不同的间隔对data.table中不同组中的数据执行线性回归? 我目前正在使用plyr进行此操作,但是对于大型数据集,它变得非常慢。非常感谢任何加快这一过程的帮助。

我有一个数据表,其中包含10天内10次CO2测量,10个地块和3个围栏。不同的日子属于不同的时间段,如下所述。

我想在每个时期使用不同的计数间隔进行线性回归,以确定每个围栏,地块和日间组合的CO2变化率。第1阶段应在计数1-5期间回归CO2,使用1-7回收期间2,使用1-9回收期间3。

CO2 <- rep((runif(10, 350,359)), 300) # 10 days, 10 plots, 3 fences
count <- rep((1:10), 300) # 10 days, 10 plots, 3 fences
DOY <-rep(rep(152:161, each=10),30) # 10 measurements/day, 10 plots, 3 fences
fence <- rep(1:3, each=1000) # 10 days, 10 measurements, 10 plots 
plot <- rep(rep(1:10, each=100),3) # 10 days, 10 measurements, 3 fences
flux <- as.data.frame(cbind(CO2, count, DOY, fence, plot))
flux$period <- ifelse(flux$DOY <= 155, 1, ifelse(flux$DOY > 155 & flux$DOY < 158, 2, 3))
flux <- as.data.table(flux)

我期待一个输出,它给出了每个情节,围栏和DOY的R2拟合和斜率。

我提供的数据是一个小子样本,我的实际数据有1 * 10 ^ 6行。以下工作,但很慢:

model <- function(df)
{lm(CO2 ~ count, data = subset(df, ifelse(df$period == 1,count>1 &count<5,
ifelse(df$period == 2,count>1 & count<7,count>1 & count<9))))}

model_flux <- dlply(flux, .(fence, plot, DOY), model)

rsq <- function(x) summary(x)$r.squared
coefs_flux <- ldply(model_flux, function(x) c(coef(x), rsquare = rsq(x)))
names(coefs_flux)[1:5] <- c("fence", "plot", "DOY", "intercept", "slope")

1 个答案:

答案 0 :(得分:3)

这是一种“data.table”方式:

library(data.table)
flux <- as.data.table(flux)
setkey(flux,count)
flux[,include:=(period==1 & count %in% 2:4) | 
                (period==2 & count %in% 2:6) | 
                (period==3 & count %in% 2:8)]
flux.subset <- flux[(include),]
setkey(flux.subset,fence,plot,DOY)

model <- function(df) {
  fit <- lm(CO2 ~ count, data = df)
  return(list(intercept=coef(fit)[1], 
              slope=coef(fit)[2],
              rsquare=summary(fit)$r.squared))
}
coefs_flux <- flux.subset[,model(.SD),by="fence,plot,DOY"]

除非我遗漏了某些内容,否则您在每次调用model(...)时所做的子集都是不必要的。您可以在开头的一个步骤中按期间对计数进行分段。除了dlply(...)返回数据帧并且此代码生成数据表之外,此代码产生与您相同的结果。它在这个测试数据集上的速度并不快。