为每个水平的因子拟合一个lm模型

问题描述 投票:0回答:2

[我正在尝试编写一个遍历因子每个级别的函数(或使用purrr::map()),并对因子等于该级别的数据子集拟合lm()模型。

[使用mtcars做一个简单的可重现示例,只需说我想为lm的每个值使用不同的mtcars$gear模型。我将从使其成为一个因素开始,因为我的真正问题涉及通过一个因素进行迭代:

library(tidyverse)

mtcars <- mtcars %>% 
  mutate(factor_gear = factor(gear))

我希望该函数适合factor_gear的每个级别。级别通过以下方式给出:

levels(mtcars$factor_gear)

  [1] "3" "4" "5"

所以我要寻找的输出将是:

fit1 <- lm(mpg ~ cyl, data = mtcars %>% filter(factor_gear=="3"))
fit2 <- lm(mpg ~ cyl, data = mtcars %>% filter(factor_gear=="4"))
fit3 <- lm(mpg ~ cyl, data = mtcars %>% filter(factor_gear=="5"))

fits <- list(fit1, fit2, fit3)

我已经开始使用该功能,但无法使其正常工作。

我认为函数应该:

  1. 将因子的每个水平放入向量中
  2. 为每个级别运行一个lm模型。
fit_each_level <- function(factor_variable) {

  # trying to: 1. get every level of of the factor into a vector
  factor_levels <- levels(df_cars$factor_variable)

  # trying to: 2. run an lm model for each level.
  for i in factor_levels {
    fit <- mtcars %>% filter(factor_variable==i [# every value of segment_levels]) %>% 
    lm(mpg ~ cyl, data = . )
  }

}

fit_each_level(factor_gear)

如果功能运行良好,我最终将能够在另一个因素上做到这一点,例如:

mtcars <- mtcars %>% 
  mutate(factor_carb = factor(carb))

fit_each_level(factor_carb)
r tidyverse purrr
2个回答
0
投票

您可以nest数据帧,并使用map为每个lm应用factor_gear

library(dplyr)

mtcars %>%
  group_by(factor_gear) %>%
  tidyr::nest() %>%
  mutate(model = map(data, ~lm(mpg ~ cyl, data = .x)))

#  factor_gear data               model 
#  <fct>       <list>             <list>
#1 4           <tibble [12 × 11]> <lm>  
#2 3           <tibble [15 × 11]> <lm>  
#3 5           <tibble [5 × 11]>  <lm>  

在新的dplyr中,您可以使用cur_data引用组中的当前数据,从而避免了需要nestmap

mtcars %>%
  group_by(factor_gear) %>%
  summarise(model = list(lm(mpg ~ cyl, data = cur_data())))

0
投票

请确保您具有最新版本的dplyr(1.0.0)。然后您可以使用:

model_coefs <- function(formula, data) {
  coefs <- lm(formula, data)$coefficients
  data.frame(coef = names(coefs), value = coefs)
}

mtcars %>%
  dplyr::mutate(factor_gear = factor(gear)) %>%
  dplyr::nest_by(factor_gear) %>%
  dplyr::summarise(model_coefs(mpg ~ cyl, data)) %>% 
  tidyr::pivot_wider(names_from = coef, values_from = value)
# A tibble: 3 x 3
# Groups:   factor_gear [3]
  factor_gear `(Intercept)`   cyl
  <fct>               <dbl> <dbl>
1 3                    29.8 -1.83
2 4                    41.3 -3.59
3 5                    40.6 -3.2 

© www.soinside.com 2019 - 2024. All rights reserved.