为什么R的功能不能返回“正确”的答案

时间:2013-03-31 04:58:44

标签: r function

我正在写一个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 != opendoors != pick消除了门AB以及D。但是,我收到了多个BC。有谁看到发生了什么?

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"

1 个答案:

答案 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

发生了什么事?由于pq的大小相同,因此将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,因为您不寻找索引。您可以在此处直接使用逻辑来获取结​​果。希望这会有所帮助。