将竞争模型拟合到dplyr/tidyr/broom框架内的嵌套数据中



我正在尝试将模型子集适合于嵌套的数据框架。虽然我见过许多将同一模型拟合到不同数据组的示例,但我还没有遇到将不同模型拟合到组织为嵌套数据框架的数据集的示例。

作为一个例子,我从R For Data Science"Many Models"一节中获取了代码。在这里,目标是将相同的模型适用于不同的国家(群体)。我希望做的是扩大这一点,并将多种不同的竞争模式适应不同的国家(群体)。理想情况下,每个相互竞争的模型将作为一个新列存储在嵌套的数据框架中。

提前感谢您的帮助!

# Example code 
library(dplyr)
library(ggplot2)
library(modelr)
library(purrr)
library(tidyr)
library(gapminder)
# Create nested data
by_country <- gapminder %>% 
  group_by(country, continent) %>% 
  nest()
# Model 1
country_model <- function(df) {
  lm(lifeExp ~ year, data = df)
}
# Map model 1 to the data
by_country <- by_country %>% 
  mutate(model = map(data, country_model))
# Model 2
country_model2 <- function(df) {
  lm(lifeExp ~ year + gdpPercap, data = df)
}
# Map Model 2 to the data
by_country <- by_country %>% 
  mutate(model2 = map(data, country_model2))

更新为了澄清我的问题,我知道我可以通过调用每个模型的突变来手动完成此操作。我认为我所追求的是更灵活的东西,几乎类似于下面的代码。然而,这些函数不是"runif"、"rnorm"one_answers"rpois",而是对模型函数的调用。例如"country_model"one_answers"country_model2"。希望这对你有所帮助。

# Example code
 sim <- dplyr::frame_data(
  ~f,      ~params,
  "runif", list(min = -1, max = -1),
  "rnorm", list(sd = 5),
  "rpois", list(lambda = 10)
 )
sim %>% dplyr::mutate(
  samples = invoke_map(f, params, n = 10)
)

下面是使用更新中提到的invoke_map函数的方法。

它涉及创建三个函数。这些函数:1. 创建一个指定模型的数据框架2. 使用invoke_map函数将这些模型应用于您的数据3.重塑结果,以便它们可以作为列添加到原始by_country数据框架

中。


# Example code 
library(dplyr)
library(ggplot2)
library(modelr)
library(purrr)
library(tidyr)
library(gapminder)
# Create nested data
by_country <- gapminder %>% 
  group_by(country, continent) %>% 
  nest()
# Function that creates dataframe suitable for invoke_map function
create_model_df  <- 
  function(x){  
    dplyr::frame_data(
      ~model_name,    ~f,     ~params,
      "country_model", "lm", list(formula =as.formula("lifeExp ~ year + gdpPercap"), data = x ),
      "country_model2","lm", list(formula =as.formula("lifeExp ~ year"),data = x )
    )     
  }
# Function that applies invoke_map function 
apply_models  <- 
  function(x){        
    x %>% 
      mutate( model_fit = invoke_map(f, params)) 
  }
# Function that the results from invoke map
reshape_results  <- 
  function(x){   
    x %>% 
      select(model_name,model_fit) %>% spread(model_name,model_fit)
  }
# Apply these functions 
by_country %>% 
  mutate(model_df = data %>% 
           map(create_model_df) %>% 
           map(apply_models) %>% 
           map(reshape_results)) %>% 
  unnest(model_df) 
#> # A tibble: 142 x 5
#>        country continent              data country_model country_model2
#>         <fctr>    <fctr>            <list>        <list>         <list>
#>  1 Afghanistan      Asia <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  2     Albania    Europe <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  3     Algeria    Africa <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  4      Angola    Africa <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  5   Argentina  Americas <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  6   Australia   Oceania <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  7     Austria    Europe <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  8     Bahrain      Asia <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#>  9  Bangladesh      Asia <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#> 10     Belgium    Europe <tibble [12 x 4]>      <S3: lm>       <S3: lm>
#> # ... with 132 more rows

最新更新