【问题标题】:Splitting data and running linear regression loop拆分数据并运行线性回归循环
【发布时间】:2020-07-12 16:32:11
【问题描述】:

我见过很多类似的问题,但是我想写的循环中有一个关键是我缺少的。我有一组包含约 4,000 个不同键的数据集,对于每个键,有约 1,000 个观察值。我已经过滤掉了一个键来隔离该键的观察结果,运行线性回归,检查模型假设,一切看起来都不错。但是,我想遍历这个数据集并为每个键运行线性回归。然后我将要存储系数、pvalues、R^2 等并一起查看它们。

这是我的数据示例:

Key y1 x1 x2
A   10 1  3
A   11 2  4 
A   12 3  5
B   13 4  6 
B   14 5  7
B   15 6  8
C   16 7  9 
C   17 8  1
C   18 9  2

我已经跑了:

datA <- data %>% filter(key=='A')
lm(y1 ~ x1 + x2, data = datA)

然后对键 B 和 C 重复此操作。我在这里看到的每个问题都是查看整个集合的不同变量的循环,而不是拆分行上的数据。

但我需要再做 4000 次。非常感谢编写此循环的任何帮助(我在编写循环方面很糟糕)。

【问题讨论】:

    标签: r loops regression lm


    【解决方案1】:

    还可以使用 broom 包将输出整理成更易读的形式。

    list_models <- lapply(split(data, data$Key), function(x) lm(y1 ~ x1 + x2, data = x))
    
    library(broom)
    
    as_tibble(do.call(rbind, lapply(list_models, broom::tidy)))
    
    # A tibble: 7 x 5
      term        estimate  std.error statistic    p.value
      <chr>          <dbl>      <dbl>     <dbl>      <dbl>
    1 (Intercept) 9.00e+ 0   2.22e-15   4.05e15   1.57e-16
    2 x1          1.00e+ 0   1.03e-15   9.73e14   6.54e-16
    3 (Intercept) 9.00e+ 0   4.59e-15   1.96e15   3.25e-16
    4 x1          1.00e+ 0   9.06e-16   1.10e15   5.77e-16
    5 (Intercept) 9.00e+ 0 NaN        NaN       NaN       
    6 x1          1.00e+ 0 NaN        NaN       NaN       
    7 x2          3.02e-16 NaN        NaN       NaN  
    

    【讨论】:

    • 我正在尝试很多不同的东西,但我只是不认为我的本地机器足够强大来运行它。我收到一个错误:Error: cannot allocate vector of size XX.x Mb 这是否只是因为我的机器功能不够强大,无法运行 4000 个键,每个键有 900 多个观察值,每个键有 10 个以上的参数?
    • 所以,我已经努力清理我的内存,顺便说一下,我可以很快地运行它,但是你认为有什么方法可以将 Key 值添加到 @987654323 @?
    • 你必须将它包含在模型中。
    【解决方案2】:

    比@RonakShah 的答案优雅得多,您可以按您的键分组并为每个键汇总,同时提取感兴趣的值以获得下表:

    library(dplyr)
    
    df %>% group_by(Key) %>%
      summarise(Intercept = lm(y1 ~ x1 + x2)$coefficients[1],
                Coeff_x1 = lm(y1 ~ x1 + x2)$coefficients[2],
                Coeff_x2 = lm(y1 ~ x1 + x2)$coefficients[3],
                R2 = summary(lm(y1 ~ x1 + x2))$r.squared,
                pvalue = summary(lm(y1 ~ x1 + x2))$coefficients["x1",4])
    
    # A tibble: 3 x 6
      Key   Intercept Coeff_x1  Coeff_x2    R2     pvalue
      <chr>     <dbl>    <dbl>     <dbl> <dbl>      <dbl>
    1 A            9.     1.00 NA            1   8.00e-16
    2 B            9.     1.00 NA            1   7.00e-16
    3 C            9.     1.00  7.86e-16     1 NaN       
    

    【讨论】:

    • 这实际上效果很好,因为我可以从模型摘要中提取我想要为整个模型集突出显示的特征。它确实比@RonakShah 需要更多的编码,但这确实工作得很好。
    【解决方案3】:

    您可以split 数据并将lm 应用于每个块。

    list_models <- lapply(split(df, df$Key), function(x) lm(y1 ~ x1 + x2, data = x))
    

    tidyverse 的方式是:

    library(dplyr)
    library(purrr)
    
    list_models <- df %>% group_split(Key) %>% map(~lm(y1 ~ x1 + x2, data = .x))
    

    它为每个人 Key 返回一个模型。

    list_models
    #$A
    #Call:
    #lm(formula = y1 ~ x1 + x2, data = x)
    
    #Coefficients:
    #(Intercept)           x1           x2  
    #          9            1           NA  
    
    #$B
    #Call:
    #lm(formula = y1 ~ x1 + x2, data = x)
    
    #Coefficients:
    #(Intercept)           x1           x2  
    #          9            1           NA  
    
    #$C
    #Call:
    #lm(formula = y1 ~ x1 + x2, data = x)
    
    #Coefficients:
    #(Intercept)           x1           x2  
    #   9.00e+00     1.00e+00     7.86e-16  
    

    【讨论】:

    • 这很好用。只是为了跟进任何感兴趣的人,我使用list_models_df &lt;- as.data.frame(do.call(rbind, list_models)) 获得了一个包含所有模型参数的格式良好的数据框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 2013-11-06
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多