【问题标题】:R fitting competing models to nested data within the dplyr/tidyr/broom frameworkR 将竞争模型拟合到 dplyr/tidyr/broom 框架内的嵌套数据
【发布时间】:2016-08-18 17:43:12
【问题描述】:

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

作为示例,我从 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))

更新 为了澄清我的问题,我知道我可以手动执行此操作,并为每个模型调用 mutate。我认为我追求的是更灵活的东西,几乎类似于下面的代码。但是,这些函数将调用模型函数,而不是函数“runif”、“rnorm”和“rpois”。例如“country_model”和“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)
)

【问题讨论】:

  • 我可能错过了您的目标。你不能把这两个模型放在同一个mutate 中吗?即mutate(model = map(data, country_model), model2 = map(data, country_model2))
  • 嗨,AO,是的,这肯定行得通。我认为我正在寻找一个更灵活的过程。因此,不是以这种方式输入每个模型,而是以某种方式传递它们(可能在一个列表中?)然后做一些更像 pmap 的东西,它将每个不同的模型映射到数据?

标签: r dplyr tidyr


【解决方案1】:

这是一种使用更新中提到的 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

【讨论】:

    猜你喜欢
    • 2015-12-27
    • 1970-01-01
    • 2017-02-28
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 2020-04-08
    相关资源
    最近更新 更多