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

R函数内多重抽样问题:glm模型未使用抽样子集数据

问题分析与解决方案

嘿,我帮你找到了这个问题的根源,这其实是R里公式和数据框交互的一个常见小坑!

为什么模型会用到全部数据?

你遇到的核心问题出在公式eq1的定义方式上:你写的eq1 <- df$zeroFac ~ df$goal + df$City_Pop是直接引用了全局环境里df的整列数据,而不是用列名的形式。

当你在glm里指定data = t1时,glm会优先遵循公式里明确写的全局变量(也就是整个df的列),完全忽略data参数指定的子集t1——这就导致模型偷偷用了全部数据,而不是你拆分出来的1/4子集。

另外你的函数还有个小瑕疵:train <- data.frame(cbind(...))这种写法会把传入的列合并成数据框,但列名会变成X1、X2、X3,和你公式里的列名完全不匹配,这也加重了问题。

怎么修正?

我们需要从两个关键地方调整:

1. 改用列名定义公式

公式应该写成zeroFac ~ goal + City_Pop,只写列名,不要加df$前缀。这样glm才会去data参数指定的数据框里找对应的列,而不是直接调用全局变量。

2. 调整函数的数据传入逻辑

不要把列分开传入,直接传入整个数据框,这样函数里的train就是完整的原数据框,列名也和公式完美匹配,逻辑更清晰。

下面是修正后的完整代码:

测试数据(保持不变)

zeroFac <- c(1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1)
goal <- c(8.412055, 7.528869, 8.699681, 10.478752, 9.210440, 10.308986, 10.126671, 11.002117, 10.308986, 7.090910, 10.819798, 7.824446, 8.612685, 7.601402, 10.126671, 7.313887, 5.993961, 7.313887, 8.517393, 12.611541)
City_Pop <- c(11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613, 11.64613)
df <- data.frame(zeroFac,goal,City_Pop)

修正后的函数与调用

forestModel <- function(eq1, data){ 
  # 直接传入完整数据框,不用再手动合并
  train <- data
  
  # 拆分数据集的逻辑不变
  set.seed(123)
  ss <- sample(1:4, size = nrow(train), replace=TRUE, prob = c(0.25,0.25,0.25,0.25))
  t1 <- train[ss==1,]
  
  # 现在glm会乖乖使用t1里的数据,因为公式用的是列名
  m <- glm(eq1, family = binomial(link = 'logit'), data = t1)
  summary(m)
}

# 公式只用列名,去掉df$
eq1 <- zeroFac ~ goal + City_Pop
# 调用时传入公式和完整数据框
forestModel(eq1, df)

怎么验证修正有效?

你可以在函数里加两行代码验证:

print(nrow(t1))  # 输出子集t1的行数,这里set.seed(123)后应该是5
print(nrow(model.frame(m)))  # 输出模型用到的行数,应该和t1的行数一致

如果两个数字相同,就说明模型确实用了t1的数据,而不是全部数据。

额外选项:保留原传入列的方式

如果你一定要保持原来传入单独列的方式,那需要给合并后的train设置正确的列名,让它和公式匹配:

forestModel <- function(eq1, ...){ 
  train <- data.frame(...)
  # 给数据框设置和公式对应的列名
  colnames(train) <- c("zeroFac", "goal", "City_Pop")
  
  set.seed(123)
  ss <- sample(1:4, size = nrow(train), replace=TRUE, prob = c(0.25,0.25,0.25,0.25))
  t1 <- train[ss==1,]
  
  m <- glm(eq1, family = binomial(link = 'logit'), data = t1)
  summary(m)
}

eq1 <- zeroFac ~ goal + City_Pop
forestModel(eq1, df$zeroFac, df$goal, df$City_Pop)

不过这种方式不如直接传整个数据框清晰,容易出错,所以更推荐第一种修正方案。

内容的提问来源于stack exchange,提问作者Clinton Woods

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:28