向量元素名稱

R 的向量有一個很特別的地方就是每一個元素都可以有一個自己的名稱,替向量的元素標上個別的名稱可以讓程式碼更容易被閱讀。在建立向量時,我們可以使用 name = value 的方式指定元素的名稱:

c(foo = 2, bar = 4)
foo bar 
  2   4

如果遇到空白或是其他特殊字元,可以使用雙引號將名稱包起來:

c(foo = 2, bar = 4, "hello world" = 6, 8)
         foo         bar hello world             
          2           4           6           8

一般的向量可以使用 names 函數來指定向量的名稱:

x <- 1:4
names(x) <- c("foo", "bar", "hello world", "")
x
        foo         bar hello world             
          1           2           3           4

若要取得向量元素的名稱,可以使用 names 函數:

names(x)
[1] "foo"         "bar"         "hello world" ""

如果遇到沒有名稱的向量,names 會傳回 NULL

names(1:10)
NULL

索引向量

若要存取向量中部分的元素,可以使用索引向量(indexing vectors)配合中括號([])來達成,而索引向量的使用方式有四種,分別為邏輯向量、正整數向量、負整數向量與字元向量,以下是這四種索引向量的使用方式。

邏輯向量

這種情況下,索引向量必須和被挑選元素的向量長度一致。向量中對應索引向量為 TRUE 的元素將會被選出,而那些對應 FALSE 的元素則被忽略。例如:

x <- c(1, 2, NA,4)
y <- x[!is.na(x)]

這會將 x 向量中非 NA 的元素選出來,並依照原本的順序指定給 y,若 x 中包含 NA 元素,則所得到的 y 向量長度會比 x 向量的長度短。

另一個較複雜的例子:

x <- c(0, -1, -2, NA, 4, 6)
x <- x + 1
z <- x[(!is.na(x)) & x > 0]

這個例子是把 x 每個元素都加一,然後選出非 NA 且大於 0 的元素,依照原本的順序指定給 z

正整數向量

這種情況下,索引向量中的每個元素必須是 {1, 2, …, length(x)} 的其中一個(length(x) 為向量 x 的長度),索引向量中索引對應的元素將會被選出,並且依照索引向量中的順序傳回,這種索引向量的長度沒有限制,所選出的向量長度會與索引向量的長度相同,例如 x[6] 表示 x 的第六個元素,此外也可以重複取出多個元素:

x <- 10:20
y <- x[1:5]
z <- x[ c(1, 2, 3, 1, 2, 3) ]

這樣所得到的 yx 的前 5 個元素,而 z 則為 c(10, 11, 12, 10, 11, 12)

以下是一個更複雜的例子:

labs <- c("x", "y")[rep(c(1, 2, 2, 1), times = 4)]

會產生一個長度為 16,由 "x", "y", "y", "x" 重複四次而構成的向量。

rep() 為重複某個向量的函數。

負整數向量

這種索引向量與正整數向量規則一樣,負數的意思是將指定的元素排除,將剩餘的元素選出,例如:

x <- 10:20
y <- x[-(1:5)]

所得到的 yc(15, 16, 17, 18, 19, 20)

字元向量

這種索引向量只能用在可以用 names 屬性區別其元素的向量,在使用之前必須以 names 函數先設定 names 屬性,例如:

fruit <- c(5, 10, 1, 20)
names(fruit) <- c("orange", "banana", "apple", "peach")
lunch <- fruit["apple"]

使用字元向量取出多個元素:

dinner <- fruit[c("orange", "peach")]

使用字串向量的好處就是容易記,這在使用 data frames 的時候效果比較明顯。

以上就是四種索引向量的使用方式。

索引運算式也可以用在指定向量的元素上,在這種情況下只有那些被索引向量指定的元素會被更動,例如:

x <- c(1, 2, NA, NA, 3)
x[is.na(x)] <- 0

只會將 x 向量中的 NA 元素設為 0,其餘的元素不變。而

y <- c(-1, -2, 0, 1, 2)
y[y < 0] <- -y[y < 0]

是將 y 取絕對值,與下面這個作法相同

y <- c(-1, -2, 0, 1, 2)
y <- abs(y)

例外狀況

雖然索引向量的使用方式有好多種,通常一個問題可以有好多種解決方案,但是這幾種索引向量不可以隨意混用,例如若把正整數向量與負整數向量混用的話,會產生錯誤,而且也不具任何意義:

x <- 6:10
x[c(2, -2)]

這樣會產生錯誤:

Error in x[c(2, -2)] : 只有負數下標中才能有 0

如果索引向量中含有缺失值 NA,則篩選出來的向量中對應的位置也會是 NA

x[c(1, NA, 5)]
[1]  6 NA 10

這是邏輯向量的例子:

x[c(TRUE, FALSE, NA, FALSE, TRUE)]
[1]  6 NA 10

缺失值如果跟負整數向量混用的話,也會造成沒有意義的錯誤:

x[c(-2, NA)]
Error in x[c(-2, NA)] : 只有負數下標中才能有 0

如果正整數索引向量指定的索引超出向量的長度,就會產生 NA(不會有錯誤訊息):

x[7]
[1] NA

這種狀況雖然不會產生錯誤,但是在撰寫程式時建議還是確保索引向量不要超過向量為佳,這樣可以降低程式出錯的機率。

如果使用浮點數作為索引向量的值,這些浮點數小數點以下的值會被捨去,自動被轉換為整數,例如:

x[2.7] # 2.7 轉為 2
[1] 7
x[-2.7] # -2.7 轉為 -2
[1]  6  8  9 10

which 函數

which 函數可以檢查邏輯向量,傳回該向量中所有 TRUE 元素的位置,例如:

x <- 10:20
which(x %% 7 == 3)
[1] 1 8

這個例子是利用 which 找出 x 向量中所有除以 7 餘數為 3 的元素位置。

另外 which.minwhich.max 分別等同於 which(min(x))which(max(x)),不過其的執行效率更好:

which.min(x)
[1] 1
which.max(x)
[1] 11