我正在遵循R for Data Science的Many Models示例来生成单个多元线性回归模型。如下面的可重现示例所示,我的数据框由三列组成:id, val1, val2, val3,
。我可以使用map
函数拟合线性模型,如哈德利的书中所述。但是,我一直在努力从每个模型中提取系数,并将这些值逐列地加回到my.list
内的数据帧中。当前存储模型系数的方式使调用代码的其他部分变得困难/麻烦。
到目前为止,我想出的最好的办法是列出一个my.list
的长度,并通过遍历my.list
:Name1, Name2, Name3
中的每个数据帧来提取系数。这意味着现在我在全局环境中还有另一个列表,coef.list
不再包含Name1, Name2, Name3
中的因素my.list
;现在这些已替换为[[1]], [[2]], [[3]]
。
在使用多个模型时,有人可以建议一种“更清洁”的方法来提取模型系数吗?我的首选输出将只是为每个系数intercept, val1, val2
创建一列。这些列将放在Name1, Name2, Name3
内的现有数据帧my.list
中,以便我可以直接在数据帧上使用mutate
:
# reproducible example
set.seed(1363)
d1 <- data.frame(id=c("Name1", "Name2", "Name3"),
val1=c(rnorm(n=15, mean=5)),
val2=c(rnorm(n=15, mean=3)),
val3=c(rnorm(n=15, mean=8)))
# linear model function
lm.fun <- function(df){
lm(val3 ~ val1+val2, data = df)
}
# map lm function
d1 <- d1 %>%
group_by(id) %>%
nest() %>%
mutate(model = map(data, lm.fun)) %>%
unnest(data, .drop = FALSE)
#split data frame by 'id' and convert into list
my.list <- split(d1, d1$id)
# make list of coefficients
coef.list <- list(length(my.list))
for (i in seq_along(my.list)) {
coef.list[[i]] <- my.list[[i]][["model"]][[1]][["coefficients"]]
}
>head(coef.list, n=1)
[[1]]
(Intercept) val1 val2
9.03278337 -0.07096932 0.02119088
期望的输出
my.list$Name1
id val1 val2 val3 intc coef1 coef2
Name1 1 2 3 9.03 -.070 .021
Name1 3 1 5 9.03 -.070 .021
Name1 2 6 8 9.03 -.070 .021
答案 0 :(得分:2)
给定数据sapply
(包含d1
列,使用model
:
coeff <- sapply(d1$model, function(x) return(coefficients(x)))
library(dplyr)
bind_cols(d1, data.frame(t(coeff))) %>%
rename_at(6:8, ~ c("intc", "coef1", "coef2")) %>%
distinct(id, .keep_all = TRUE)
答案 1 :(得分:1)
根据描述,如果我们需要使用系数创建一些列,则一个选择是将do
与group_by
一起使用。按“ id”分组后,将系数提取为list
和do
列中的rename
(如果需要)
library(tidyverse)
d1 %>%
group_by(id) %>%
do(data.frame(., as.list(coef(lm(val3 ~ val1 + val2, data = .))))) %>%
rename_at(5:7, ~c("intc", "coef1", "coef2"))
# A tibble: 15 x 7
# Groups: id [3]
# id val1 val2 val3 intc coef1 coef2
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Name1 6.76 2.64 9.85 9.03 -0.0710 0.0212
# 2 Name1 6.78 1.52 6.94 9.03 -0.0710 0.0212
# 3 Name1 4.14 4.31 8.30 9.03 -0.0710 0.0212
# 4 Name1 5.55 2.16 9.97 9.03 -0.0710 0.0212
# 5 Name1 6.18 3.64 8.32 9.03 -0.0710 0.0212
# 6 Name2 6.08 1.12 9.96 7.33 0.468 -0.488
# 7 Name2 3.54 4.71 6.43 7.33 0.468 -0.488
# 8 Name2 5.66 4.54 8.69 7.33 0.468 -0.488
# 9 Name2 6.88 4.15 7.79 7.33 0.468 -0.488
#10 Name2 4.89 1.27 8.72 7.33 0.468 -0.488
#11 Name3 6.41 4.38 6.22 20.1 -2.15 0.118
#12 Name3 5.06 3.28 9.42 20.1 -2.15 0.118
#13 Name3 6.25 3.16 8.15 20.1 -2.15 0.118
#14 Name3 6.03 3.63 7.78 20.1 -2.15 0.118
#15 Name3 6.51 1.46 5.90 20.1 -2.15 0.118
或者我们可以使用broom
包函数。 tidy
,glance
之类的函数提取感兴趣的列(以及更多)。 nest
分组后的数据集之后,构建模型,并使用tidy
,select
感兴趣的列和unnest
library(broom)
d1 %>%
group_by(id) %>%
nest %>%
mutate(model1 = map(data, ~
lm(val3 ~ val1 + val2, data = .) %>%
tidy %>%
dplyr::select(term, estimate) %>%
spread(term, estimate) %>%
rename_all(~ c("intc", paste0("coef", 1:2))))) %>%
unnest(model1) %>%
unnest(data)
# A tibble: 15 x 7
# id intc coef1 coef2 val1 val2 val3
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Name1 9.03 -0.0710 0.0212 6.76 2.64 9.85
# 2 Name1 9.03 -0.0710 0.0212 6.78 1.52 6.94
# 3 Name1 9.03 -0.0710 0.0212 4.14 4.31 8.30
# 4 Name1 9.03 -0.0710 0.0212 5.55 2.16 9.97
# 5 Name1 9.03 -0.0710 0.0212 6.18 3.64 8.32
# 6 Name2 7.33 0.468 -0.488 6.08 1.12 9.96
# 7 Name2 7.33 0.468 -0.488 3.54 4.71 6.43
# 8 Name2 7.33 0.468 -0.488 5.66 4.54 8.69
# 9 Name2 7.33 0.468 -0.488 6.88 4.15 7.79
#10 Name2 7.33 0.468 -0.488 4.89 1.27 8.72
#11 Name3 20.1 -2.15 0.118 6.41 4.38 6.22
#12 Name3 20.1 -2.15 0.118 5.06 3.28 9.42
#13 Name3 20.1 -2.15 0.118 6.25 3.16 8.15
#14 Name3 20.1 -2.15 0.118 6.03 3.63 7.78
#15 Name3 20.1 -2.15 0.118 6.51 1.46 5.90
或者不使用broom
d1 %>%
group_by(id) %>%
nest %>%
mutate(model = map(data, ~ lm(val3 ~ val1 + val2, data = .) %>%
coef %>%
as.list %>%
as_tibble)) %>%
unnest(model) %>%
unnest(data)
如果我们只需要每个'id'的摘要输出
d1 %>%
group_by(id) %>%
nest %>%
mutate(model1 = map(data, ~
lm(val3 ~ val1 + val2, data = .) %>%
tidy %>%
dplyr::select(term, estimate) %>%
spread(term, estimate) %>%
rename_all(~ c("intc", paste0("coef", 1:2))))) %>%
dplyr::select(-data) %>%
unnest
或者使用data.table
,我们可以更简洁地做到这一点,在对'id'进行分组并通过提取模型的:=
作为{来分配(coef
)新列之后, {1}}
list
或者如果我们不想更新初始数据,请执行library(data.table)
setDT(d1)[, c('intc', 'coef1', 'coef2') :=
as.list(coef(lm(val3 ~ val1 + val2))), id]
d1[order(id)]
# id val1 val2 val3 intc coef1 coef2
# 1: Name1 6.755964 2.642874 9.849828 9.032783 -0.07096932 0.02119088
# 2: Name1 6.776666 1.522431 6.937053 9.032783 -0.07096932 0.02119088
# 3: Name1 4.141883 4.307537 8.301940 9.032783 -0.07096932 0.02119088
# 4: Name1 5.551850 2.163882 9.971588 9.032783 -0.07096932 0.02119088
# 5: Name1 6.179506 3.635832 8.319042 9.032783 -0.07096932 0.02119088
# 6: Name2 6.083243 1.116293 9.960934 7.325156 0.46840770 -0.48806159
# 7: Name2 3.536476 4.708967 6.427627 7.325156 0.46840770 -0.48806159
# 8: Name2 5.663909 4.541081 8.691523 7.325156 0.46840770 -0.48806159
# 9: Name2 6.883746 4.150780 7.791050 7.325156 0.46840770 -0.48806159
#10: Name2 4.890291 1.269559 8.723792 7.325156 0.46840770 -0.48806159
#11: Name3 6.414915 4.383609 6.220188 20.106581 -2.14601530 0.11770877
#12: Name3 5.059774 3.276510 9.421862 20.106581 -2.14601530 0.11770877
#13: Name3 6.251416 3.157157 8.147720 20.106581 -2.14601530 0.11770877
#14: Name3 6.028100 3.630858 7.783118 20.106581 -2.14601530 0.11770877
#15: Name3 6.505153 1.460564 5.895564 20.106581 -2.14601530 0.11770877
join
注意:“ d1”是初始数据集
答案 2 :(得分:1)
library(tidyverse)
d1%>%
group_by(id)%>%
mutate(s=toString(coef(lm(val3~val1+val2))))%>%
separate(s,c("intercept","coef1","coef2"),sep=",",convert = T)%>%
arrange(id)
# A tibble: 15 x 7
# Groups: id [3]
id val1 val2 val3 intercept coef1 coef2
<fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Name1 6.76 2.64 9.85 9.03 -0.0710 0.0212
2 Name1 6.78 1.52 6.94 9.03 -0.0710 0.0212
3 Name1 4.14 4.31 8.30 9.03 -0.0710 0.0212
4 Name1 5.55 2.16 9.97 9.03 -0.0710 0.0212
5 Name1 6.18 3.64 8.32 9.03 -0.0710 0.0212
6 Name2 6.08 1.12 9.96 7.33 0.468 -0.488
7 Name2 3.54 4.71 6.43 7.33 0.468 -0.488
8 Name2 5.66 4.54 8.69 7.33 0.468 -0.488
9 Name2 6.88 4.15 7.79 7.33 0.468 -0.488
10 Name2 4.89 1.27 8.72 7.33 0.468 -0.488
11 Name3 6.41 4.38 6.22 20.1 -2.15 0.118
12 Name3 5.06 3.28 9.42 20.1 -2.15 0.118
13 Name3 6.25 3.16 8.15 20.1 -2.15 0.118
14 Name3 6.03 3.63 7.78 20.1 -2.15 0.118
15 Name3 6.51 1.46 5.90 20.1 -2.15 0.118