如何获得 。在 dplyr::do 中正确解释的公式中?
How to get . in a formula correctly interpreted inside dplyr::do?
我有以下数据框:
input.df <- dplyr::data_frame(x = rnorm(4),
y = rnorm(4),
`z 1` = rnorm(4))
我想对每一列与其他列进行多元回归,并从每个模型中提取 R 平方。这意味着我可以 运行 以下代码:
summary(lm(x ~ ., data = input.df))
summary(lm(y ~ ., data = input.df))
summary(lm(`z 1` ~ ., data = input.df))
并记下 R 平方。
我想自动执行此任务并有两列数据框,其中第一列是因变量,第二列是 R 平方。
这是我试过的:
n <- ncol(input.df)
replicate(n, input.df, simplify = F) %>%
dplyr::bind_rows() %>%
dplyr::mutate(group = rep(names(.), each = nrow(.) / n)) %>%
dplyr::group_by(group) %>%
dplyr::do({
tgt.var <- .$group[1]
# How do I get the formula to interpret . as all variables?
lm(get(tgt.var) ~ ., data = .) %>%
broom::glance() %>%
dplyr::select(r.squared)
})
我对卡住的部分发表了评论。我收到以下错误:
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels
不确定如何直接解决您的问题。这是另一种方法,可以为单独的模型推导具有因变量的 data.frame 和 r.sq。
cond <- matrix(c(1,0,0,0,1,0,0,0,1), ncol=3)
colnames(cond)<- colnames(input.df)
cond
x y z 1
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
xy <- lapply(1:nrow(cond), function(v)
list(y = colnames(cond)[which(cond[v,]==1)] %>% paste0("`", ., "`"),
x = colnames(cond)[which(cond[v,]==0)] %>% paste0("`", ., "`") %>% paste(., collapse="+")))
lm.form <- lapply(1:length(xy), function(v) paste(xy[[v]]$y, xy[[v]]$x, sep="~") %>% as.formula)
lm.mod <- lapply(lm.form, function(v)lm(v, data=input.df))
data.frame(pred = lapply(xy, function(v) v["x"]) %>% unlist,
r.sq = lapply(lm.mod, function(v) summary(v)$r.sq)%>% unlist)
pred r.sq
1 `y`+`z 1` 0.5806704
2 `x`+`z 1` 0.8500431
3 `x`+`y` 0.8335421
我认为您构建数据框有点过于复杂了。不需要 replicate
因为你是 运行 同一数据集上的所有回归。您可以只使用 purrr
中的 map
,我们的想法是尝试类似
的方法
library(purrr)
names(input.df) %>%
map(~ lm(get(.) ~ ., data = input.df))
这运行没有错误,但没有给出预期的结果。原因是 get(.)
作为新变量添加到数据集中,因此例如第一个回归是 x ~ x + y + `z 1`
这不是我们想要的。通过如下更改 lm
中的公式,可以轻松解决此问题
names(input.df) %>%
map(~ lm(formula(paste0('`', ., '` ~ .')), data = input.df))
(请注意,由于第三个变量的名称,需要包含转义反引号,否则就没有必要了)。这现在给出了预期的结果。如果您不想保留所有内容并想提取 r2,您可以这样做
names(input.df) %>%
map(~ lm(formula(paste0('`', ., '` ~ .')), data = input.df)) %>%
map(summary) %>%
map_dbl('r.squared')
我有以下数据框:
input.df <- dplyr::data_frame(x = rnorm(4),
y = rnorm(4),
`z 1` = rnorm(4))
我想对每一列与其他列进行多元回归,并从每个模型中提取 R 平方。这意味着我可以 运行 以下代码:
summary(lm(x ~ ., data = input.df))
summary(lm(y ~ ., data = input.df))
summary(lm(`z 1` ~ ., data = input.df))
并记下 R 平方。
我想自动执行此任务并有两列数据框,其中第一列是因变量,第二列是 R 平方。
这是我试过的:
n <- ncol(input.df)
replicate(n, input.df, simplify = F) %>%
dplyr::bind_rows() %>%
dplyr::mutate(group = rep(names(.), each = nrow(.) / n)) %>%
dplyr::group_by(group) %>%
dplyr::do({
tgt.var <- .$group[1]
# How do I get the formula to interpret . as all variables?
lm(get(tgt.var) ~ ., data = .) %>%
broom::glance() %>%
dplyr::select(r.squared)
})
我对卡住的部分发表了评论。我收到以下错误:
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels
不确定如何直接解决您的问题。这是另一种方法,可以为单独的模型推导具有因变量的 data.frame 和 r.sq。
cond <- matrix(c(1,0,0,0,1,0,0,0,1), ncol=3)
colnames(cond)<- colnames(input.df)
cond
x y z 1
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
xy <- lapply(1:nrow(cond), function(v)
list(y = colnames(cond)[which(cond[v,]==1)] %>% paste0("`", ., "`"),
x = colnames(cond)[which(cond[v,]==0)] %>% paste0("`", ., "`") %>% paste(., collapse="+")))
lm.form <- lapply(1:length(xy), function(v) paste(xy[[v]]$y, xy[[v]]$x, sep="~") %>% as.formula)
lm.mod <- lapply(lm.form, function(v)lm(v, data=input.df))
data.frame(pred = lapply(xy, function(v) v["x"]) %>% unlist,
r.sq = lapply(lm.mod, function(v) summary(v)$r.sq)%>% unlist)
pred r.sq
1 `y`+`z 1` 0.5806704
2 `x`+`z 1` 0.8500431
3 `x`+`y` 0.8335421
我认为您构建数据框有点过于复杂了。不需要 replicate
因为你是 运行 同一数据集上的所有回归。您可以只使用 purrr
中的 map
,我们的想法是尝试类似
library(purrr)
names(input.df) %>%
map(~ lm(get(.) ~ ., data = input.df))
这运行没有错误,但没有给出预期的结果。原因是 get(.)
作为新变量添加到数据集中,因此例如第一个回归是 x ~ x + y + `z 1`
这不是我们想要的。通过如下更改 lm
中的公式,可以轻松解决此问题
names(input.df) %>%
map(~ lm(formula(paste0('`', ., '` ~ .')), data = input.df))
(请注意,由于第三个变量的名称,需要包含转义反引号,否则就没有必要了)。这现在给出了预期的结果。如果您不想保留所有内容并想提取 r2,您可以这样做
names(input.df) %>%
map(~ lm(formula(paste0('`', ., '` ~ .')), data = input.df)) %>%
map(summary) %>%
map_dbl('r.squared')