向量化 if 判斷式

一般的 if 判斷式沒辦法直接處理布林向量的判斷,如果將布林向量放進 if 判斷式中,會以第一個元素為準,其餘的元素則會捨棄不用:

if(c(TRUE, FALSE)) message("OK.")
OK.
Warning message:
In if (c(TRUE, FALSE)) message("OK.") :
  條件的長度 > 1,因此只能用其第一元素

若需要一次對一整個布林向量作判斷,可以改用 ifelse 這個函數,其第一個參數為布林向量,第二個參數是條件判斷為 TRUE 時要執行的運算,第二個參數則是條件判斷為 FALSE 時要執行的運算:

ifelse(c(TRUE, FALSE, TRUE), "Good", "Bad")
[1] "Good" "Bad"  "Good"

這是另外一個例子:

x <- c(3:-2)
sqrt(ifelse(x >= 0, x, NA))
[1] 1.732051 1.414214 1.000000 0.000000
[5]       NA       NA

若第二個與第三個參數為向量時,ifelse 就會依照第一個參數的布林向量來取出對應的值:

idx <- rep(c(TRUE, FALSE), 6)
ifelse(idx, 1:3, -1:-6)
 [1]  1 -2  3 -4  2 -6  1 -2  3 -4  2 -6

switch 判斷式

ifelse 的配合之下,雖然可以處理多重條件的判斷,但是這樣的寫法在條件比較多的時候,會顯得比較雜亂:

x <- "mean"
y <- 1:10
if ( x == "mean" ) {
  mean(y)
} else if ( x == "sd" ) {
  sd(y)
} else if ( x == "median" ) {
  median(y)
} else if ( x == "sum" ) {
  sum(y)
}
[1] 5.5

這時候可以改用 switch 的寫法:

switch(x,
  mean = mean(y),
  sd = sd(y),
  median = median(y),
  sum = sum(y))
[1] 5.5

若要處理所有條件都不符合的預設狀況,可以加入一個沒有名稱的參數,這樣在所有條件都不符合時,預設就會傳回該參數值:

z <- "nothing"
switch(z,
  mean = mean(y),
  sd = sd(y),
  median = median(y),
  sum = sum(y),
  99)
[1] 99

如果要執行多行運算式,就要使用大括號包起來:

z <- "custom"
switch(z,
  mean = mean(y),
  sd = sd(y),
  median = median(y),
  sum = sum(y),
  custom = {
    y2 <- y * 1.2 + pi / 2
    prod(sin(y2))
  })
[1] -0.00102691

如果 switch 第一個參數放置的是數值,後續的選項可以不需要指定名稱,這種狀況 switch 會直接取出該數值所對應的參數:

switch(
  3,
  "first",
  "second",
  "third",
  "fourth"
)
[1] "third"

上面這樣的用法就沒有預設的選項可以使用,如果想要使用數值來當作判斷的依據,但是又需要預設選項時,可以採用這樣的做法:

switch(
  as.character(328),
  "328" = "the anser 328",
  "default anser"
)
[1] "the anser 328"