【问题标题】:R nested models: create column of model formulasR嵌套模型:创建模型公式列
【发布时间】:2019-01-26 17:50:49
【问题描述】:

如何从模型的嵌套数据框中创建一列公式(例如 y ~ xy ~ log(x) 或 ...)?

在下面的尝试中,模型列包含 R 平方最大值的模型。创建一列模型公式的目的是确定每一行中使用了哪个模型。

library(tidyverse)
library(broom)

df <- gapminder::gapminder %>% 
  select(country, x = year, y = lifeExp) %>%
  group_by(country) %>%
  nest()

rsq_f <- function(model){summary(model)$r.squared}

best_model <- function(df){
  models <- list(
    lm(formula = y ~ x, data = df),
    lm(formula = y ~ log(x), data = df),
    lm(formula = log(y) ~ x, data = df),
    lm(formula = log(y) ~ log(x), data = df)
  )

  R_squared <- map_dbl(models, rsq_f)
  best_model_num <- which.max(R_squared)

  models[best_model_num][[1]]    
}

models <- df %>%
  mutate(
    model = map(data, best_model),
    rsq = map(model, broom::glance) %>% map_dbl("r.squared"),
    fun_call = map(model, formula)
  )

输出是

> models
# A tibble: 142 x 5
   country     data              model      rsq fun_call     
   <fct>       <list>            <list>   <dbl> <list>       
 1 Afghanistan <tibble [12 x 2]> <S3: lm> 0.949 <S3: formula>
 2 Albania     <tibble [12 x 2]> <S3: lm> 0.912 <S3: formula>
 3 Algeria     <tibble [12 x 2]> <S3: lm> 0.986 <S3: formula>
 4 Angola      <tibble [12 x 2]> <S3: lm> 0.890 <S3: formula>
 5 Argentina   <tibble [12 x 2]> <S3: lm> 0.996 <S3: formula>
 6 Australia   <tibble [12 x 2]> <S3: lm> 0.983 <S3: formula>
 7 Austria     <tibble [12 x 2]> <S3: lm> 0.994 <S3: formula>
 8 Bahrain     <tibble [12 x 2]> <S3: lm> 0.968 <S3: formula>
 9 Bangladesh  <tibble [12 x 2]> <S3: lm> 0.997 <S3: formula>
10 Belgium     <tibble [12 x 2]> <S3: lm> 0.995 <S3: formula>
# ... with 132 more rows

我想实际查看模型使用的公式,而不是&lt;S3: formula&gt;

【问题讨论】:

  • 你能...%&gt;% unnest(fun_call) 吗?
  • models %&gt;% unnest(fun_call) 错误:每一列必须是向量列表或数据框列表 [fun_call] - 猜测这意味着没有......
  • 每个lm 模型应该有一个terms 元素,这是一个list 使用的公式,如果你使用as.character(lm$terms),你可能有一些东西可以使用..
  • 因为这给你的格式不完全正确,你需要重新排列它,比如:paste(as.character(my_lm$terms)[2],as.character(my_lm$terms)[1], as.character(my_lm$terms)[-c(1:2)]) 如果我理解正确你的问题,这会给你一个带有正确公式的字符串..
  • 公式不是小标题可以以表格格式显示的原子类型。您只是想在控制台中查看它吗?然后你应该编写自己的打印函数。或者像其他人提到的,将公式转换为字符值进行显示。

标签: r lm purrr broom


【解决方案1】:

根据 RLave 的评论,答案只是添加as.character()

models <- df %>%
  mutate(
    model = map(data, best_model),
    rsq = map(model, broom::glance) %>% map_dbl("r.squared"),
    fun_call = map(model, formula) %>% as.character()
  )

给出:

# A tibble: 142 x 5
   country     data              model      rsq fun_call  
   <fct>       <list>            <list>   <dbl> <chr>     
 1 Afghanistan <tibble [12 x 2]> <S3: lm> 0.949 y ~ log(x)
 2 Albania     <tibble [12 x 2]> <S3: lm> 0.912 y ~ log(x)
 3 Algeria     <tibble [12 x 2]> <S3: lm> 0.986 y ~ log(x)
 4 Angola      <tibble [12 x 2]> <S3: lm> 0.890 y ~ log(x)
 5 Argentina   <tibble [12 x 2]> <S3: lm> 0.996 y ~ x     
 6 Australia   <tibble [12 x 2]> <S3: lm> 0.983 log(y) ~ x
 7 Austria     <tibble [12 x 2]> <S3: lm> 0.994 log(y) ~ x
 8 Bahrain     <tibble [12 x 2]> <S3: lm> 0.968 y ~ log(x)
 9 Bangladesh  <tibble [12 x 2]> <S3: lm> 0.997 log(y) ~ x
10 Belgium     <tibble [12 x 2]> <S3: lm> 0.995 log(y) ~ x
# ... with 132 more rows

【讨论】:

    【解决方案2】:

    为了让自己更清楚,我将发布一个示例作为答案,如果我理解正确,您会寻求包含公式的列,例如字符串 "y ~ x"

    假设我们有一个简单的lm:

    x <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14)
    y <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69)
    my_lm <- lm(y~ x)   
    

    通过查看术语,您有公式,只是排列不正确:

    as.character(my_lm[["terms"]])
    # [1] "~" "y" "x"
    

    你只需要重新排列前两个词:

    paste(as.character(my_lm$terms)[2],as.character(my_lm$terms)[1], as.character(my_lm$terms)[-c(1:2)])
    # [1] "y ~ x"
    

    这可以用mutate 分配给一个列。

    【讨论】:

    • 这同样适用my_lm$call$formula,无需重新安排
    • 这给出了一个字符串:as.character(my_lm)[11]
    • 这也有效:as.character(summary(my_lm))[2] 奇怪的是,formula(my_lm) %&gt;% as.character() 给出了重新排列的公式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多