这是一个很难回答的问题,因为我无法提供实际的复制数据(抱歉,数据太大/敏感),但我会感激任何人的想法。我在这里使用示例数据来显示代码的结构,尽管此代码不会产生我在下面详细说明的错误。
我有一个复杂的函数,我在其中执行多重回归来隔离交互效应,并使用精彩的
plot_slopes
包中的 marginaleffects
函数将它们绘制在一起。我的代码结构如下。
library(tidyverse)
library(marginaleffects)
outcome_var_list = c("mpg","cyl","hp")
interact_var_list = c("am","wt")
subset_var_list = c("3","4")
combos = expand.grid(outcome_var_list, subset_var_list)
model_ <- function(k,c){
mtcars = mtcars[mtcars$gear == c,]
outcome_var_list = outcome_var_list[outcome_var_list == k]
results = list()
for (r in interact_var_list) {
f = paste(k, "~", r, "*factor(vs)")
m = lm(f, subset(mtcars, carb %in% c(1,2,3,4)))
s = plot_slopes(m, variables = r, condition = "vs", draw = FALSE)
tmp = s[, c("estimate", "conf.low", "conf.high", "vs")]
tmp$outcome = k
tmp$regressor = r
results = c(results, list(tmp))
}
results = do.call("rbind", results)
plot1 = results %>%
mutate(min = min(conf.low), max = max(conf.high)) %>%
ggplot(aes(x=factor(vs),
y=estimate,
color = regressor,
ymin=conf.low,
ymax=conf.high)) +
geom_errorbar(position = position_dodge(0.4)) +
geom_point(position = position_dodge(0.4)) +
scale_x_discrete(expand = c(0,0)) +
theme_light() +
ggtitle(label = paste0("Model 1: ",k)) +
theme(plot.title = element_text(hjust = 0.5)) +
labs(y= "Interaction Coefficient", x = "X") +
theme(plot.title = element_textbox_simple(vjust=-1)) +
theme(plot.margin = margin(2,0,0,0, "cm")) +
theme(axis.text.x = element_text(size = 5))
ggsave(plot1,file=paste0("plot_",k,".png"),path=paste0(c))
}
safe_model <- safely(model_)
iterate <-mapply(safe_model,combos$Var1,combos$Var2)
当我在添加额外的
subset_var_list
之前运行此操作时,一切都生成得很好。
但是,当我添加子集 var 并切换到 mapply 时,我现在为数据的整个子集生成模型,其中只有几个
outcome_var
可以生成要保存的图。我认为这是由于缺乏覆盖范围或其他原因,所以我删除了safely
,这揭示了以下错误:
Error: Unable to compute predicted values with this model. You can try to supply a different dataset to the `newdata` argument.
If this does not work, you can file a report on the Github Issue Tracker:
https://github.com/vincentarelbundock/marginaleffects/issues
我再次假设这是由于缺乏覆盖/变化,所以我尝试为每个单独的交互回归手动运行
plot_slopes
,而不是通过函数,并且每个单独的图/回归都成功为其中一个子集生成,否则不会生成绘图。所以这似乎不是模型的问题/缺乏变化。
我可能会误解错误消息中提出的
newdata
参数是如何工作的,但它似乎拥有执行任务的完整数据,并且这应该没有任何优势。是否有理由解释为什么回归/斜率模型可以单独/手动生成,而当放在这个函数中时却无法预测它们?我怎样才能解决这个问题并为每个子集创建我需要的所有绘图?
无论如何使用 tidyverse,您可以创建一个具有所需组合的网格(
expand.grid
),并使用一列来扩展此数据框来保存模型,另一列来保存绘图对象以供进一步使用(将它们保存为副作用)一路上)。
注意使用 rowwise()
和 list()
将任意对象放入数据框单元格中:
library(dplyr)
library(ggplot2)
## subset mtcars once only (unless you want different subsets
## per row):
d <- subset(mtcars, carb %in% 1:4)
result <-
expand.grid(outcome = c('mpg','cyl','hp'),
regressor = c('am', 'wt')
) |>
rowwise() |>
mutate(model = list(
lm(sprintf('%s ~ %s * factor(vs)', outcome, regressor), data = d)
),
slopes = list(slopes(model)),
plots = list({p <- ggplot(data = slopes) +
geom_point(aes(factor(vs), estimate, color = term))
## save the plot as you go:
ggsave(p, filename = sprintf('plot_%s_%s.png', outcome, regressor))
p ## return the plot object
})
)
输出:
## # A tibble: 12 x 6
## # Rowwise:
## outcome gear regressor model slopes plots
## <fct> <fct> <fct> <list> <list> <list>
## 1 mpg 3 am <lm> <slopes [60 x 15]> <gg>
## 2 cyl 3 am <lm> <slopes [60 x 15]> <gg>
## 3 hp 3 am <lm> <slopes [60 x 15]> <gg>
根据需要挑选和重复使用对象,例如。克:
> result$model[[3]]
Call:
lm(formula = sprintf("%s ~ %s * factor(vs)", outcome, regressor),
data = d)
Coefficients:
(Intercept) am factor(vs)1 am:factor(vs)1
194.17 -50.42 -92.02 28.85