R 有一組運算子,和其他許多程式語言相同:
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
if-then-else 的基本形式如下:
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
在這個例子中,布林值前後的括號( )與主體前後的大括號{ }都是必要的。
簡單的if敘述可以縮寫成:
if (x == 0) return("success")
先預告一下之後會介紹的vector-filtering概念:括號()裡的條件子句必須求出單一的TRUE/FALSE。
在比較中加入向量通常會得到一個布林向量,因此需要用聚合函式包起來,例如all()(所有值都是 TRUE 嗎?)或any()(至少有一個值是 TRUE 嗎?)。
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse 函式另一種 if-else 形式可能很有用,前提是結果只會有 true/false 兩種。
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse()正好接受三個參數:
TRUE時的值FALSE時的值。向量輸入也可以接受,此時輸出也會是向量。
在這種情況下,要確保兩個分支產生相同型別的資料:數字、字元、邏輯值等等。
這部分會在vector-functions概念中介紹。
兩個結果(上例中的"big", "small")都應該是單一值。
可惜的是,在這裡給出更長的向量,很可能會讓 R 做出令人困惑又出乎意料的事,而且不會出現警告訊息。
if_else 函式R 語言的維護者奉行一項政策:盡可能避免破壞性變更。 這有助於維護 CRAN 中大量的第三方套件,卻也限制了用現代程式設計概念更新 base R 的能力。
近年來,陸續有一些套件問世,它們延伸、有時甚至取代了 R 的功能,這些套件奠基於數十年來對原始 R 設計優缺點的經驗。
這些套件組成了tidyverse集合。
它們在 2023 年被加入 Exercism 的測試執行器,你可以在練習中使用它們。
我們的 R 軌道比 tidyverse 的加入早了許多年,因此你可能會注意到,許多社群解答都堅持使用基礎語言。
dplyr 套件dplyr主要用來操作資料框(之後會在課程中介紹)。
你可以用library(dplyr)加在程式碼開頭,或用library(tidyverse)加入整個集合。
你可能會看到關於名稱被遮蔽的警告訊息,但這很少造成問題。
就目前這個概念而言,值得提一下if_else函式。
它大致上類似 base R 中的ifelse。
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
主要差異在於,if_else可以接受一個選用的第四個引數,用來處理 R 中以NA表示的缺失值。
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
你也可能會發現,if_else的錯誤訊息比舊版的ifelse好得多。
載入dplyr套件之後,你還可以使用between()函式。
R 不允許串接比較,所以1 <= x <= 5會產生錯誤訊息。
載入dplyr之後,between(x, 1, 5)等於x >= 1 & x <= 5,而且可能更好讀。
上下限都包含在內。