我正在写一个Monty Hall problem的变体,建立在另一个人的代码上。不同的是,我有“n”门而不是3门。让我们说n = 4
这个问题。门标有A, B, C and D
。
代码如下:
n <- 4
doors <- LETTERS[seq( from = 1, to = n )]
xdata = c()
for(i in 1:10000) {
prize <- sample(doors)[1]
pick <- sample(doors)[1]
open1 <- doors[which(doors != pick & doors != prize)]
open <- sample(open1,n-2)
# the line with the problem
switchyes <- doors[which( doors != open & doors != pick)]
if(pick==prize) {
xdata <- c(xdata, "noswitchwin")
}
if(switchyes==prize) {
xdata=c(xdata, "switchwin")
}
}
当我运行代码时,我收到警告:
There were 50 or more warnings (use warnings() to see the first 50)
问题似乎是由于该行:
switchyes <- doors[which( doors != open & doors != pick)]
这应该只返回1个项目(C
),因为语句doors != open
和doors != pick
消除了门A
和B
以及D
。但是,我收到了多个B
和C
。有谁看到发生了什么?
length(which(xdata == "switchwin"))
# [1] 4728
length(which(xdata == "noswitchwin"))
# [1] 2424
switchyes
# [1] "B" "C"
open
# [1] "B" "D"
open1
# [1] "B" "D"
pick
# [1] "A"
prize
# [1] "C"
答案 0 :(得分:2)
当LHS和RHS大小不同时,您遇到的问题是使用!=
:
p <- letters[1:4]
# [1] "a" "b" "c" "d"
q <- c("a", "e", "d", "d")
# [1] "a" "e" "d" "d"
p == q
# [1] TRUE FALSE FALSE TRUE
p != q
# [1] FALSE TRUE TRUE FALSE
发生了什么事?由于p
和q
的大小相同,因此将p
的每个元素与相应索引q
的值进行比较。现在,如果我们将q
更改为:
q <- c("b", "d")
p == q
# [1] FALSE FALSE FALSE TRUE
这里发生了什么?由于q
(RHS)的长度不等于 p
(LHS),q
会被回收以达到p
的长度。也就是说,
# p q p q
a == b, b == d # first two comparisons
c == b, d == d # recycled comparisons
相反,你应该使用
!(doors %in% open) & !(doors %in% pick).
另外,注意到!A AND !B = !(A OR B)
。所以,您可以将其重写为
!(doors %in% open | doors %in% pick)
反过来,这可以简化为只使用一个%in%
:
!(doors %in% c(open, pick))
此外,您可以使用Negate
创建一个函数,比如%nin%
(对应!(x %in% y
)并替换上述语句中的!
和%in%
如下:
`%nin%` <- Negate(`%in%`)
doors %nin% c(open, pick) # note the %nin% here
所以基本上你的语句分配给switchyes
只能读取:
# using %bin% after defining the function
switchyes <- doors[doors %nin% c(open, pick)]
您不需要在此使用which
,因为您不寻找索引。您可以在此处直接使用逻辑来获取结果。希望这会有所帮助。