這是 R 中一個很重要的概念。 為了幫助你理解各種可能性,考慮各類函式的輸入與輸出的維度,會很有幫助。
我們已經看過一些函式,它們接受一個向量,並回傳單一的類純量值:
v <- 1:5
length(v)
#> [1] 5
sum(v)
#> [1] 15
許多統計函式也屬於這一類,例如 mean()。
至於邏輯向量,則有 all() 和 any(),它們會回傳單一的 TRUE 或 FALSE。
R 中許多函式會直接作用在整個向量上,通常會產生向量輸出。 大多數數學函式都屬於這一類:
sq <- c(4, 9, 16, 25)
sqrt(sq) # square root
#> [1] 2 3 4 5
這不只是簡潔方便,還省去了在其他語言中很常見的迴圈、列表推導式或遞迴的需求。 在 R 中,向量化函式的執行速度通常比那些技巧快得多。
你其實已經用過向量化函式,只是可能沒意識到有這麼多。比較一下這些:
v <- c(2, 7, 9)
w <- c(3, 1, 5)
v + w
#> [1] 5 8 14
"+"(v, w)
#> [1] 5 8 14
那些熟悉的中綴運算子,其實只是底層向量化函式的語法糖!在這裡就是 "+"()。
要排序向量時,可以用 sort() 回傳排序後的值,用 order() 回傳索引:
v <- c("I", "am", "not", "in", "order")
sort(v)
#> [1] "am" "I" "in" "not" "order"
order(v)
#> [1] 2 1 4 3 5
預設是遞增排序。
需要的話可以指定 decreasing = TRUE,或使用 rev() 反轉現有的向量。
v <- c("I", "am", "not", "in", "order")
sort(v, decreasing = TRUE)
#> [1] "order" "not" "in" "I" "am"
rev(1:4)
#> [1] 4 3 2 1
另外還有像 cumsum() 和 cumprod() 這樣的函式,會由左至右處理輸入向量,產生累積的向量輸出:
cumsum(1:5)
#> [1] 1 3 6 10 15 # sums
cumprod(1:5)
#> [1] 1 2 6 24 120 # equivalent to factorials
上述範例類似許多函式式語言中的 foldl 運算,差別在於輸出是包含所有中間值的向量。
這個概念的延伸也可以用來比較向量。
例如,考慮成對取最大值的函式 pmax():
v
#> [1] 2 7 9
w
#> [1] 3 1 5
pmax(v, w)
#> [1] 3 7 9 # max of each pairwise comparison
這個函式以及其他類似的函式,也接受任意數量的輸入向量,不限於兩個。
上面的例子使用長度相同的向量。 正如向量篩選概念中所討論的,R 會使用循環來延伸某種程度上「太短」的向量。 再強調一次:請謹慎使用,最好只用在長度為 1 的向量上。
pmax(v, 5)
#> [1] 5 7 9
這種情況比較少見,但要寫出表面上「純量輸入、向量輸出」的函式相當容易。
當套用到向量輸入時,輸出會是二維的 matrix(會在後續概念中介紹)。