首先,ifelse
確實不始終評估兩種表述 - 只有在有測試向量都TRUE
和FALSE
元素。
ifelse(TRUE, 'foo', stop('bar')) # "foo"
,在我看來:
ifelse
應該不將在非量化的情況下使用。這是總是慢和更容易出錯使用ifelse
超過if
/else
:
# This is fairly common if/else code
if (length(letters) > 0) letters else LETTERS
# But this "equivalent" code will yield a very different result - TRY IT!
ifelse(length(letters) > 0, letters, LETTERS)
在量化的情況下,雖然,ifelse
可以是一個不錯的選擇 - 但要注意的是結果的長度和屬性可能不是你所期望的(如上所述,我認爲ifelse
在這方面被打破)。
下面是一個示例:tst
的長度爲5並且有一個類。我期望的結果是長度爲10,沒有類,但這不是什麼情況 - 它得到一個不兼容的類和長度5!
# a logical vector of class 'mybool'
tst <- structure(1:5 %%2 > 0, class='mybool')
# produces a numeric vector of class 'mybool'!
ifelse(tst, 101:110, 201:210)
#[1] 101 202 103 204 105
#attr(,"class")
#[1] "mybool"
爲什麼我會期望長度爲10?因爲在R「循環」的大部分功能較短矢量以匹配較長:
1:5 + 1:10 # returns a vector of length 10.
...但是ifelse
僅週期是/否參數以匹配TST參數的長度。
爲什麼我會期望從測試對象中複製類(和其他屬性)到而不是?因爲返回邏輯向量的<
不會從它的(通常是數字)參數中複製類和屬性。它不這樣做,因爲它通常是非常錯誤的。
1:5 < structure(1:10, class='mynum') # returns a logical vector without class
最後,「自己動手」可以更有效率嗎?那麼,ifelse
似乎不是像if
這樣的基元,它需要一些特殊的代碼來處理NA
。如果您沒有NA
s,那麼自己動手可能會更快。
tst <- 1:1e7 %%2 == 0
a <- rep(1, 1e7)
b <- rep(2, 1e7)
system.time(r1 <- ifelse(tst, a, b)) # 2.58 sec
# If we know that a and b are of the same length as tst, and that
# tst doesn't have NAs, then we can do like this:
system.time({ r2 <- b; r2[tst] <- a[tst]; r2 }) # 0.46 secs
identical(r1, r2) # TRUE
謝謝!我現在沒時間看這個,但今晚晚些時候我會這樣做。感謝您的評論和示例。 –
優秀的建議和例子。謝謝! –
請注意'ifelse'確實執行向量回收 - 如果'yes'或'no'變量的長度與'test'不相等,它們將被回收。這意味着如果所有矢量長度相等,則示例末尾的測試代碼只會得出相同的結果。試試這個輸入數據:'tst < - sample(c(TRUE,FALSE),1e2,replace = TRUE); a < - 1:100; b < - - (1:50);' – Andrie