R - 循环 lm() 按列遍历具有缺失值的 Dataframe

R - Loop lm() columnwise through Dataframe with missing Values

我正在处理一个由至少三个变量(波长、辐照度、x)组成的数据框,我已经对这些变量进行了调整,以便每个波长都是一个新行,从而允许我 运行 lm( ) 在每个波长上提取系数,这样我就可以看到 x 如何随波长和辐照度变化。

但是,我能够让它工作的唯一方法是在每个波长上显式 运行ning lm()。这对于较大的数据帧是不可行的,这些数据帧将具有数百个参数,这些参数会随着波长和辐照度的变化而变化。

我觉得可以使用 'apply' 或编写循环来解决这个问题,但我没有运气让它们起作用。

请参阅下面的问题示例。

我还是个新手,所以不胜感激

irr = rnorm(33, 10, 3)
wave = c(290, 290, 290, 300, 300, 300, 310, 310, 310, 320, 320, 320, 330, 330, 330, 340, 340, 340, 350, 350, 350, 360, 360, 360, 370, 370, 370, 380, 380, 380, 400, 400, 400)
x = rnorm(33, 50, 2)
df <- as.data.frame(cbind(wave, irr, x))
df_wide <- df %>%
  pivot_wider(names_from = "wave",
              values_from = "x")
"290_lm" <- lm(df_wide$`290` ~ df_wide$irr) 
"300_lm" <- lm(df_wide$`300` ~ df_wide$irr) #etc through each wavelength

## Attempt at loop

for (i in 2:(ncol(df_wide))){
  irr <- df_wide[2][i]
  lm_function <- paste(irr,
                       sep = "~")
  df_lm = lm(lm_function, 
             data = df_wide[2:12])
}

当您使用长格式时,这可能会容易很多。只需使用 lapply 对您的数据进行子集化。使用 setNames 生成的列表会得到好听的名字。

res <- setNames(lapply(unique(df$wave), function(w) 
  lm(x ~ irr, data=df[df$wave %in% w, ])),
  paste0("wave.", unique(df$wave)))
res
# $wave.290
# 
# Call:
#   lm(formula = x ~ irr, data = df[df$wave %in% w, ])
# 
# Coefficients:
#   (Intercept)          irr  
# 36.837        1.503  
# 
# 
# $wave.300
# 
# Call:
#   lm(formula = x ~ irr, data = df[df$wave %in% w, ])
# 
# Coefficients:
#   (Intercept)          irr  
# 54.3785      -0.5586 
# [...]

据我所知,根据你的描述,你的问题与 purrr::map 的示例相同,这避免了扩大范围的需要。

library(dplyr)
library(purrr)

results_list <- 
  df %>% 
  split(.$wave) %>% 
  map(~ lm(x ~ irr, data = .x)) %>% 
  map(summary)

results_list$`350`
#> 
#> Call:
#> lm(formula = x ~ irr, data = .x)
#> 
#> Residuals:
#>      19      20      21 
#>  0.2924 -2.2947  2.0023 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)  
#> (Intercept)  52.7276     6.2200   8.477   0.0748 .
#> irr          -0.4977     0.6229  -0.799   0.5708  
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 3.059 on 1 degrees of freedom
#> Multiple R-squared:  0.3897, Adjusted R-squared:  -0.2206 
#> F-statistic: 0.6385 on 1 and 1 DF,  p-value: 0.5708

根据您的数据

irr = rnorm(33, 10, 3)
wave = c(290, 290, 290, 300, 300, 300, 310, 310, 310, 320, 320, 320, 330, 330, 330, 340, 340, 340, 350, 350, 350, 360, 360, 360, 370, 370, 370, 380, 380, 380, 400, 400, 400)
x = rnorm(33, 50, 2)
df <- as.data.frame(cbind(wave, irr, x))

reprex package (v0.3.0)

于 2020-05-12 创建

附加解决方案

library(tidyverse)
library(generics)
df %>% 
  group_by(wave) %>% 
  nest() %>% 
  mutate(model = map(data, ~ lm(x ~ irr, data = .x) %>% tidy)) %>% 
  select(-data) %>% 
  unnest(model)

或如下:

df <- data.frame(
  irr = rnorm(33, 10, 3),
  wave = c(290, 290, 290, 300, 300, 300, 310, 310, 310, 
           320, 320, 320, 330, 330, 330, 340, 340, 340, 350, 350, 350, 
           360, 360, 360, 370, 370, 370, 380, 380, 380, 400, 400, 400),
  x = rnorm(33, 50, 2)

)

mylm <- function(w) {
  m <- lm(x ~ irr, data = df, subset = (wave == w))
  ## outcomment the following if you just need the parameters
  # coef(m)
}

lapply(df$wave, mylm)