You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于子集选择模型的R语言足球观赛人数预测问题

问题:regsubsets子集选择模型无法预测含NA的目标变量样本

我通过子集选择方法构建模型,目标是预测足球赛事的观赛人数(Tilskuere字段)。训练数据包含236条无缺失值的观测值,需预测3条Tilskuere为NA的未举办比赛。我将训练数据与这3条数据合并为239条的数据集,但调用预测函数时,结果仅覆盖前236条训练样本,未包含待预测的3条数据。

问题原因

自定义的predict.regsubsets函数中,model.matrix()默认会自动删除包含NA的行。待预测的3条数据中Tilskuere(模型的响应变量)为NA,因此被model.matrix过滤,导致预测结果仅返回完整的236条训练样本的预测值。

解决方法

修改自定义的predict.regsubsets函数,在生成model.matrix时添加na.action = na.pass参数,强制保留含NA的行。由于模型预测仅依赖自变量,只要待预测样本的自变量无缺失(你的代码已通过过滤保证这一点),就可以正常计算预测值。

修改后的完整代码

sl_klar = read.csv("data/fulldata 1.csv")

# 移除疫情期间数据
start_dato <- as.Date("2020-03-07")
slut_dato <- as.Date("2021-04-16")
sl_klar <- sl_klar[!(sl_klar$Dato >= start_dato & sl_klar$Dato <= slut_dato), ]

# 筛选Viborg FF主场数据并移除所有含NA的行
sl_klar <- sl_klar %>%
  filter(Hjemmehold == "Viborg FF") %>%
  na.omit()

# 删除无关变量
sl_klar = sl_klar %>%
  dplyr::select(-Fugtighed, -Fugtighed.den.sidste.time, -Vindhastighed, -Nedbør.sidste.time, 
                -Dagtype, -indbyggertal, -Populær.kanal,
                -Runde, -Helligd., -Temperatur, -ID, -Dato, -Tid,- Hjemmehold, -Udehold, -Hjemmeholdsmål, 
                -Udeholdsmål, -Ugedag, -Synlighed, -X, -Form)

# 修改后的predict.regsubsets函数:添加na.action = na.pass
predict.regsubsets <- function(object, newdata, id, ...) {
  form <- as.formula(object$call[[2]])
  # 关键修改:保留含NA的行
  mat <- model.matrix(form, newdata, na.action = na.pass)
  coefi <- coef(object, id = id)
  xvars <- names(coefi)
  mat[, xvars] %*% coefi
}

set.seed(5)
train <- sample(c(TRUE, FALSE), nrow(sl_klar), replace = TRUE)
test <- (!train)

sl_train = sl_klar[train,]
sl_test = sl_klar[test,]

# 训练子集选择模型
regfit.best <- regsubsets(Tilskuere ~ .,
                          data = sl_train, nvmax = 4)

# 10折交叉验证选择最优变量数
k <- 10
n <- nrow(sl_train)
set.seed(5)
folds <- sample(rep(1:k, length = n))
cv.errors <- matrix(NA, k, 4,
                    dimnames = list(NULL, paste(1:4)))

for (j in 1:k) { 
  best.fit <- regsubsets(Tilskuere ~ .,
                         data = sl_train[folds != j, ],
                         nvmax = 4)
  for (i in 1:4) {
    pred <- predict(best.fit, sl_train[folds == j, ], id = i)
    cv.errors[j, i] <- mean((sl_train$Tilskuere[folds == j] - pred)^2)
  }
}

mean.cv.errors <- apply(cv.errors, 2, mean)
plot(mean.cv.errors, type = "b")
best_nvar <- which.min(mean.cv.errors)

# 用最优变量数重新训练模型
reg.best <- regsubsets(Tilskuere ~ ., data = sl_train,
                       nvmax = best_nvar)
coef(reg.best, best_nvar)

# 测试集验证
pred_best_subset <- predict(reg.best, sl_test, id = best_nvar)
mse_best_subset <- mean((sl_klar[test,]$Tilskuere - pred_best_subset)^2)

# 准备待预测数据
pred.data = read.csv("data/fulldata 1.csv")

# 移除疫情期间数据
start_dato <- as.Date("2020-03-07")
slut_dato <- as.Date("2021-04-16")
pred.data <- pred.data[!(pred.data$Dato >= start_dato & pred.data$Dato <= slut_dato), ]

# 筛选Viborg FF主场数据,保留最后3条含NA的待预测样本
pred.data = pred.data %>%
  filter(Hjemmehold == "Viborg FF") %>%
  filter(
    !is.na(Tilskuere) | row_number() %in% (n() - 2):n(),
    across(everything(), ~!is.na(.) | row_number() %in% (n() - 2):n())
  )

# 删除无关变量,确保与训练数据结构一致
pred.data <- pred.data %>%
  dplyr::select(-Fugtighed, -Fugtighed.den.sidste.time, -Vindhastighed, -Nedbør.sidste.time, 
                -Dagtype, -indbyggertal, -Populær.kanal,
                -Runde, -Helligd., -Temperatur, -ID, -Dato, -Tid,- Hjemmehold, -Udehold, -Hjemmeholdsmål, 
                -Udeholdsmål, -Ugedag, -Synlighed, -X, -Form)

# 执行预测
predict_attendance <- predict(reg.best, pred.data, id = best_nvar)

# 查看完整预测结果中的最后3条待预测数据
tail(predict_attendance, 3)

结果验证

修改后运行predict_attendance会得到239条预测值,其中最后3条就是那3场待预测比赛的观赛人数,可通过tail(predict_attendance, 3)直接查看。

内容的提问来源于stack exchange,提问作者Phung Minh Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:49:50