Вложенные модели: создать столбец формул модели
Как я могу создать столбец формул (например, y ~ x
или же y ~ 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
Вместо <S3: formula>
Я бы хотел увидеть формулу, использованную моделью.
3 ответа
Основываясь на комментарии 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
Поскольку вы уже ответили на этот вопрос, я просто хотел бы подчеркнуть, насколько просто проводить групповой анализ, который вы выполняете, используя groupedstats
пакет:
# loading needed libraries
library(tidyverse)
# creating `glance` summaries
(results_df <- purrr::pmap_dfr(
.l = list(
data = list(gapminder::gapminder),
grouping.vars = alist(country),
formula = list(
lifeExp ~ year, # formula 1
lifeExp ~ log(year), # formula 2
log(lifeExp) ~ year, # formula 3
log(lifeExp) ~ log(year) # formula 4
),
output = list("glance")
),
.f = groupedstats::grouped_lm,
.id = "formula"
))
#> # A tibble: 568 x 14
#> formula country r.squared adj.r.squared sigma statistic df logLik
#> <chr> <fct> <dbl> <dbl> <dbl> <dbl> <int> <dbl>
#> 1 1 Afghan~ 0.948 0.942 1.22 181. 2 -18.3
#> 2 1 Albania 0.911 0.902 1.98 102. 2 -24.1
#> 3 1 Algeria 0.985 0.984 1.32 662. 2 -19.3
#> 4 1 Angola 0.888 0.877 1.41 79.1 2 -20.0
#> 5 1 Argent~ 0.996 0.995 0.292 2246. 2 -1.17
#> 6 1 Austra~ 0.980 0.978 0.621 481. 2 -10.2
#> 7 1 Austria 0.992 0.991 0.407 1261. 2 -5.16
#> 8 1 Bahrain 0.967 0.963 1.64 291. 2 -21.9
#> 9 1 Bangla~ 0.989 0.988 0.977 930. 2 -15.7
#> 10 1 Belgium 0.995 0.994 0.293 1822. 2 -1.20
#> # ... with 558 more rows, and 6 more variables: AIC <dbl>, BIC <dbl>,
#> # deviance <dbl>, df.residual <int>, p.value <dbl>, significance <chr>
# models with maximum R-squared values
results_df %>%
dplyr::group_by(.data = ., country) %>%
dplyr::filter(.data = ., r.squared == max(r.squared))
#> # A tibble: 142 x 14
#> # Groups: country [142]
#> formula country r.squared adj.r.squared sigma statistic df logLik
#> <chr> <fct> <dbl> <dbl> <dbl> <dbl> <int> <dbl>
#> 1 1 Argent~ 0.996 0.995 0.292 2246. 2 -1.17
#> 2 1 Cambod~ 0.639 0.603 5.63 17.7 2 -36.7
#> 3 1 Ireland 0.984 0.983 0.478 621. 2 -7.07
#> 4 1 Madaga~ 0.995 0.994 0.560 1860. 2 -8.97
#> 5 1 Maurit~ 0.998 0.997 0.408 4290. 2 -5.16
#> 6 1 Switze~ 0.997 0.997 0.215 3823. 2 2.52
#> 7 1 Vietnam 0.989 0.988 1.31 934. 2 -19.2
#> 8 1 Yemen,~ 0.981 0.979 1.59 521. 2 -21.5
#> 9 2 Afghan~ 0.949 0.944 1.20 187. 2 -18.2
#> 10 2 Albania 0.912 0.903 1.96 104. 2 -24.0
#> # ... with 132 more rows, and 6 more variables: AIC <dbl>, BIC <dbl>,
#> # deviance <dbl>, df.residual <int>, p.value <dbl>, significance <chr>
Создано 2018-08-22 пакетом представлением (v0.2.0.9000).
Для большей ясности я опубликую в качестве ответа пример, если я правильно понял, вы стремитесь получить столбец с формулой, например строку "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
в столбец.