【问题标题】:Applying an lm function to different ranges of data and separate groups using data.table使用 data.table 将 lm 函数应用于不同范围的数据和不同的组
【发布时间】:2014-03-14 15:42:12
【问题描述】:

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

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

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

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")

【问题讨论】:

    标签: r data.table plyr lm


    【解决方案1】:

    这是一个“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(...) 返回一个数据框并且此代码生成一个数据表。在这个测试数据集上并没有快多少。

    【讨论】:

    • 谢谢。这在整个数据集上要快得多,而且效果很好。在对 model(...) 的每次调用中包含子集的唯一原因是我在多个数据集上重复使用该模型。它让我不必单独对每个数据集进行子集化。
    猜你喜欢
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多