是否有 R 函数可以强制始终将两个变量添加或删除在一起?

Is there an R function that I can force two variables always to be added or removed together?

提问人:Michael 提问时间:11/6/2023 最后编辑:Michael 更新时间:11/6/2023 访问量:53

问:

我一直在包中使用来执行模型选择。我希望模型中的两个自变量始终在逐步选择(向前和向后方向)中一起添加或删除。stepAICMASS

这是我的代码:

full.model <- glm(formula=Hospital ~ A + B + C + D1 + D2, family="binomial", data=data)
MASS::stepAIC(full.model, scope = list(upper = full.model, lower = Hospital ~ A),
              direction = "both", trace = 1)

理想情况下,我希望 &(两者都是数值变量)总是一起添加或删除,但在我看来,stepAIC 没有这种灵活性。任何人都可以使用或其他 R 函数来了解如何实现这一点吗?非常感谢!D1D2stepAIC

R 型号 选择

评论

1赞 Limey 11/6/2023
如果 和 是因子,则只需创建一个新因子来定义两者之间的交互作用。Fit 而不是 和D1D2D12D12D1D2
0赞 Michael 11/6/2023
谢谢,并且是数值变量。D1D2

答:

1赞 jpsmith 11/6/2023 #1

我不知道是否有参数可以容纳此功能,但您可以手动自己执行此操作。MASS::stepAIC

假设您有以下数据:

set.seed(123)
n <- 1e3
data <- data.frame(hospital = sample(0:1, n, replace = TRUE),
                   A = as.factor(sample(LETTERS, n, replace = TRUE)),
                   B = as.factor(sample(c("Apples", "Oranges", "Grapes", "Bananas"), n, replace = TRUE)),
                   C = as.factor(sample(c("planes","trains", "automobiles"), n, replace = TRUE)),
                   D1 = runif(n),
                   D2 = runif(n))

您可以使用以下命令生成预测变量的所有组合的列表,这些变量同时包含两者或不包含任何变量,并使用:D1D2

# get all possible combinations
all_list <- do.call(c, lapply(seq_along(names(data)[-1]), combn, x = names(data[-1]), simplify = FALSE))

# keep only those with either both or no `D1` and `D2`
keeps <- lapply(all_list, \(x) sum((x %in% c("D1", "D2"))) != 1)

keeps_list <- all_list[unlist(keeps)]

如果运行,您将看到它包含所有带有 / 约束的排列的列名(出于空间考虑,此处不这样做)。print(keeps_list)D1D2

获得此列表后,可以使用以下方法遍历列表,将它们粘贴到公式中,运行模型并输出 AIC:lapply

formula_list <- lapply(keeps_list, \(x) paste0("hospital ~ ", paste(x, collapse = " + ")))

# Contains all model information
full_models <- lapply(formula_list,\(x) glm(x, family = "binomial", data = data))

其中包含所有各种组合的所有模型信息。full_modelglm()

如果要获取用于模型比较的 AIC 信息:

# extracts and organizes AIC for comparison
aic_models <- do.call(rbind, lapply(full_models, \(x) summary(x)$aic))
aic_models <- data.frame(aic_models)
rownames(aic_models) <- lapply(keeps_list, paste, collapse = "-")

#             aic_models
# A             1403.604
# B             1392.457
# C             1390.975
# A-B           1408.608
# A-C           1407.239
# B-C           1395.990
# D1-D2         1389.446
# A-B-C         1412.184
# A-D1-D2       1405.016
# B-D1-D2       1394.588
# C-D1-D2       1392.992
# A-B-D1-D2     1410.132
# A-C-D1-D2     1408.626
# B-C-D1-D2     1398.091
# A-B-C-D1-D2   1413.687

然后,如果需要,您可以将它们与完整模型 () 进行比较,并确定具有最低 AIC () 的参数组合:diffbest

aic_models[,"diff"] <- aic_models[,1] - aic_models[nrow(aic_models),1]
aic_models[,"best"] <- aic_models$aic_models == min(aic_models$aic_models)

#             aic_models        diff  best
# A             1419.566  -6.5183258 FALSE
# B             1392.836 -33.2485780 FALSE
# C             1388.043 -38.0417237  TRUE
# A-B           1424.729  -1.3556720 FALSE
# A-C           1418.896  -7.1890668 FALSE
# B-C           1392.839 -33.2454109 FALSE
# D1-D2         1390.085 -35.9994857 FALSE
# A-B-C         1424.130  -1.9541680 FALSE
# A-D1-D2       1421.337  -4.7478673 FALSE
# B-D1-D2       1394.965 -31.1196409 FALSE
# C-D1-D2       1389.972 -36.1126197 FALSE
# A-B-D1-D2     1426.671   0.5868186 FALSE
# A-C-D1-D2     1420.708  -5.3769971 FALSE
# B-C-D1-D2     1394.934 -31.1503318 FALSE
# A-B-C-D1-D2   1426.085   0.0000000 FALSE

我知道这需要一些工作,但这应该让你开始!

评论

1赞 Michael 11/8/2023
这正是我所需要的。感谢您提供详细的答案!