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

R语言蒙特霍尔问题模拟报错:sample.int无效参数及向量迭代问题

蒙特霍尔问题R语言模拟报错解决

问题场景

在统计课程中用R模拟蒙特霍尔问题,计划通过10000次实验验证换门胜率2/3、不换门胜率1/3的结论。已完成不换门的模拟,但编写主持人开门函数时遇报错:

  • 调用revealed_door函数时出现:Error in sample.int(length(x), size, replace, prob) : invalid first argument
  • 尝试用all_doors[-initial_choice]替代setdiff时,出现only 0’s may be mixed with negative subscripts错误,还出现过结果全为NA的情况

当前revealed_door函数及换门逻辑代码如下:

## 原主持人开门函数
revealed_door = function(initial_choice, car_door, all_doors){
  ## if-else to determine which doors can be revealed and reveal one
  ifelse(car_door == initial_choice, sample(setdiff(all_doors, initial_choice), 1),
         setdiff(all_doors, c(initial_choice, car_door)))
}

## 原换门逻辑
switch_wins = 0
## Switch doors
reveal = revealed_door(initial_choice, car_door, all_doors)
new_choice = all_doors[-c(reveal, initial_choice)]
## Count wins
ifelse(car_door == new_choice, switch_wins + 1, switch_wins)
total_switch_wins = sum(switch_wins)
## Divide wins by n to calculate probability
switch_win_prob = total_switch_wins / 10000
print(switch_win_prob)

注:car_door和initial_choice均为长度10000的向量,元素取自1:3;all_doors为c(1,2,3)

错误原因

  1. ifelse与sample的不兼容:ifelse是向量化操作,但sample是标量函数。当initial_choice是长度10000的向量时,setdiff(all_doors, initial_choice)会返回all_doors中不在整个initial_choice向量里的元素(而非逐元素移除对应值),导致sample的输入不符合预期,触发sample.int报错。
  2. 向量索引错误:all_doors[-initial_choice]中,若initial_choice是向量,负索引会被当成整体位置移除,而非逐元素处理,导致索引越界或逻辑错误。
  3. 换门计数逻辑错误:switch_wins = 0是单个数值,ifelse不会修改它的值,最终sum(switch_wins)始终为0。

修正代码

1. 修正主持人开门函数

使用sapply逐元素处理每一次实验的初始选择和奖品门,确保每次都正确计算主持人要打开的门:

revealed_door = function(initial_choice, car_door, all_doors) {
  sapply(seq_along(initial_choice), function(i) {
    ic = initial_choice[i]
    cd = car_door[i]
    if (cd == ic) {
      # 玩家选对了,主持人随机开剩下两扇门中的一个
      sample(setdiff(all_doors, ic), 1)
    } else {
      # 玩家选错了,主持人只能开剩下那扇没车的门
      setdiff(all_doors, c(ic, cd))
    }
  })
}

2. 修正换门计数逻辑

直接用向量运算统计获胜次数,避免单个数值的错误赋值:

# 生成10000次实验的随机数据
n = 10000
all_doors = c(1,2,3)
car_door = sample(all_doors, n, replace = TRUE)
initial_choice = sample(all_doors, n, replace = TRUE)

# 不换门的胜率(验证用)
stay_win_prob = mean(car_door == initial_choice)
cat("不换门胜率:", stay_win_prob, "\n")

# 换门逻辑
reveal = revealed_door(initial_choice, car_door, all_doors)
# 计算换门后的选择:排除初始选择和主持人打开的门
new_choice = sapply(seq_along(initial_choice), function(i) {
  setdiff(all_doors, c(initial_choice[i], reveal[i]))
})
# 统计换门获胜次数
total_switch_wins = sum(car_door == new_choice)
switch_win_prob = total_switch_wins / n
cat("换门胜率:", switch_win_prob, "\n")

运行说明

  • 运行后会输出不换门和换门的胜率,多次运行后换门胜率会趋近于2/3,不换门胜率趋近于1/3,符合蒙特霍尔问题的结论。
  • 核心修正点是逐元素处理每一次实验,而非对整个向量做批量操作,确保逻辑符合单次实验的规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:37:22