【问题标题】:how to run lm regression for every column in R如何为 R 中的每一列运行 lm 回归
【发布时间】:2017-07-16 19:52:00
【问题描述】:

我的数据框为:

df=data.frame(x=rnorm(100),y1=rnorm(100),y2=rnorm(100),y3=...)

我想运行一个循环,从第一列的第二列开始对每一列进行回归:

for(i in names(df[,-1])){
    model = lm(i~x, data=df)
}

但我失败了。关键是我想为每一列做一个回归循环,一些列名只是一个数字(例如 404.1)。我找不到使用上述命令为每一列运行循环的方法。

【问题讨论】:

  • 为什么不将这些列转换成字符串?
  • lapply(df[-1], function(y){lm(y ~ x, df)})
  • lapply( df[, -1], function( y ) lm(y ~ df$x ) )
  • 查看钴包中的函数f.build()

标签: r dataframe regression


【解决方案1】:

您的代码看起来不错,除非您在lm 中调用i,R 会将i 读取为一个字符串,您无法对其进行回归。使用get 可以拉取i 对应的列。

df=data.frame(x=rnorm(100),y1=rnorm(100),y2=rnorm(100),y3=rnorm(100))

storage <- list()
for(i in names(df)[-1]){
  storage[[i]] <- lm(get(i) ~ x, df)
}

我创建了一个空列表storage,我将用循环的每次迭代来填充它。这只是个人喜好,但我也建议您不要编写当前循环:

 for(i in names(df[,-1])){
    model = lm(i~x, data=df)
}

您将覆盖model,从而仅返回最后一次迭代结果。我建议您将其更改为列表或矩阵,您可以在其中迭代存储结果。

希望有帮助

【讨论】:

  • 这行得通!我使用模型只是为了演示。对模型使用列表也是我个人的习惯。
  • 很高兴为您提供帮助。如果我的建议适合回答您的问题,请单击勾选标记以接受它作为所选答案。
【解决方案2】:

扫帚和tidyverse的另一种解决方案:

library(tidyverse)
library(broom)
df <- data.frame(x=rnorm(100),y1=rnorm(100),y2=rnorm(100))

result <- df %>% 
  gather(measure, value, -x) %>%
  nest(-measure) %>%
  mutate(fit = map(data, ~ lm(value ~ x, data = .x)),
         tidied = map(fit, tidy)) %>%
  unnest(tidied)

【讨论】:

    【解决方案3】:
    library(tidyverse)
    df <- data.frame(x=rnorm(100),y1=rnorm(100),y2=rnorm(100))
    

    head(df)你会看到

           x          y1          y2
    1 -0.8955473  0.96571502 -0.16232461
    2  0.5054406 -2.74246178 -0.18120499
    3  0.1680144 -0.06316372 -0.53614623
    4  0.2956123  0.94223922  0.38358329
    5  1.1425223  0.43150919 -0.32185672
    6 -0.3457060 -1.16637706 -0.06561134 
    
    models <- df %>% 
      pivot_longer(
        cols = starts_with("y"),
        names_to = "y_name",
        values_to = "y_value"
      ) 
    

    之后,head(models),你会得到

           x y_name y_value
       <dbl> <chr>    <dbl>
    1 -0.896 y1      0.966 
    2 -0.896 y2     -0.162 
    3  0.505 y1     -2.74  
    4  0.505 y2     -0.181 
    5  0.168 y1     -0.0632
    6  0.168 y2     -0.536 
    

    split(.$y_name)会将所有数据按照y_name的不同层级进行拆分,对于每一部分数据,他们都会做同样的功能split(map(~lm(y_value ~ x, data = .))

    在这之后,head(models)你会得到

    $y1
    
    Call:
    lm(formula = y_value ~ x, data = .)
    
    Coefficients:
    (Intercept)            x  
        0.14924      0.08237  
    
    
    $y2
    
    Call:
    lm(formula = y_value ~ x, data = .)
    
    Coefficients:
    (Intercept)            x  
        0.11183      0.03141  
    

    如果你想整理你的结果,你可以做以下事情:

      tibble(
        dvsub = names(.),
        untidied = .
        ) %>%
      mutate(tidy = map(untidied, broom::tidy)) %>%
      unnest(tidy) 
    

    然后你会得到View(models)这样的:

      dvsub untidied     term        estimate std.error statistic p.value
      <chr> <named list> <chr>          <dbl>     <dbl>     <dbl>   <dbl>
    1 y1    <lm>         (Intercept)   0.0367    0.0939     0.391   0.697
    2 y1    <lm>         x             0.0399    0.0965     0.413   0.680
    3 y2    <lm>         (Intercept)   0.0604    0.109      0.553   0.582
    4 y2    <lm>         x            -0.0630    0.112     -0.561   0.576
    

    所以整个代码如下:

    models <- df %>% 
      pivot_longer(
        cols = starts_with("y"),
        names_to = "y_name",
        values_to = "y_value"
      ) %>%
      split(.$y_name) %>%
      map(~lm(y_value ~ x, data = .)) %>%
      tibble(
        dvsub = names(.),
        untidied = .
        ) %>%
      mutate(tidy = map(untidied, broom::tidy)) %>%
      unnest(tidy) 
    

    【讨论】:

    • 看来你的帖子主要是代码,请补充一些细节
    猜你喜欢
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 2018-08-14
    • 2015-11-20
    • 2013-05-31
    相关资源
    最近更新 更多