Data Frame 索引

data frame 的索引使用方式有許多種,向量和矩陣所使用的四種索引(正整數、負整數、邏輯與字元向量)都可以直接用於 data frame:

x.data.frame <- data.frame(
  x = letters[1:6],
  y = rnorm(6),
  z = runif(6) > 0.5
)
x.data.frame[2:4, 2]
[1] -0.2310849  1.0684388  0.9391086
x.data.frame[2:4, -2]
  x     z
2 b  TRUE
3 c  TRUE
4 d FALSE
x.data.frame[c(FALSE, TRUE, TRUE, TRUE, FALSE), c("x", "z")]
  x     z
2 b  TRUE
3 c  TRUE
4 d FALSE

只有取出 data frame 的單一行(column)時,傳回的資料類型會是向量,但若是取出多行時,傳回的資料就會是另一個 data frame:

class(x.data.frame[2:4, 2])
[1] "numeric"
class(x.data.frame[2:4, -2])
[1] "data.frame"

如果只需要選取單一行的資料,可以使用列表變數的索引方式(雙中括號 [[]] 加上正整數或名稱、錢字號 $ 加上名稱),以下幾種寫法都是相同的。

x.data.frame$x
[1] a b c d e f
Levels: a b c d e f
x.data.frame[[1]]
[1] a b c d e f
Levels: a b c d e f
x.data.frame[["x"]]
[1] a b c d e f
Levels: a b c d e f

如果要取出一行中部分的元素,可以再堆疊一個中括號來指定元素的索引:

x.data.frame$x[2:4]
[1] b c d
Levels: a b c d e f
x.data.frame[[1]][2:4]
[1] b c d
Levels: a b c d e f
x.data.frame[["x"]][2:4]
[1] b c d
Levels: a b c d e f

如果想要篩選 data frame 中的資料,可以使用條件判斷式再配合索引的方式來處理:

x.data.frame[x.data.frame$y > 0 | x.data.frame$z, "x"]
[1] a b d e f
Levels: a b c d e f

如果不想使用這麼複雜的寫法,也可以改用 subset 函數,它的功能相同,但是寫法較簡潔:

subset(x.data.frame, y > 0 | z, x)
  x
1 a
2 b
4 d
5 e
6 f

subset 函數第一個參數是要進行篩選的 data frame 變數,而第二個參數是指定列(row)的索引,第三個參數則是行(column)的索引,若最後一個行索引參數省略,就會取出所有行中的資料。

基本 Data Frame 操作

data frame 跟矩陣一樣可以使用 t 函數來轉向:

x.data.frame <- data.frame(
  x = letters[1:6],
  y = rnorm(6),
  z = runif(6) > 0.5
)
t(x.data.frame)

不過將 data frame 轉向之後,所有的資料都會換轉為同一種類型,而且轉換之後的變數會是一個矩陣。

若要結合多個 data frames,可以使用 cbindrbindrbind 在結合多個 data frames 時,會自動判斷每個行的名稱,將相同名稱的行對應起來,行的排列順序不會影響合併結果:

x.data.frame <- data.frame(
  x = letters[1:6],
  y = rnorm(6),
  z = runif(6) > 0.5
)
y.data.frame <- data.frame(
  y = rnorm(6, 7, 9),
  z = runif(6) < 0.5,
  x = letters[7:12]
)
rbind(x.data.frame, y.data.frame)
   x           y     z
1  a  -0.3059567  TRUE
2  b   0.6109400  TRUE
3  c   0.5408157 FALSE
4  d   0.8020496 FALSE
5  e  -0.9348107 FALSE
6  f   1.2134915 FALSE
7  g  -0.3173948  TRUE
8  h  25.6336216  TRUE
9  i -16.4824389  TRUE
10 j   5.3940237  TRUE
11 k  11.9232029 FALSE
12 l  16.6851942  TRUE

cbind 函數在合併 data frames 時,並不會檢查行的名稱,所以要注意行名稱重複的問題:

cbind(x.data.frame, y.data.frame)
  x          y     z           y     z x
1 a -0.3059567  TRUE  -0.3173948  TRUE g
2 b  0.6109400  TRUE  25.6336216  TRUE h
3 c  0.5408157 FALSE -16.4824389  TRUE i
4 d  0.8020496 FALSE   5.3940237  TRUE j
5 e -0.9348107 FALSE  11.9232029 FALSE k
6 f  1.2134915 FALSE  16.6851942  TRUE l

如果兩個 data frames 要依照某個特定的行來合併資料,可以使用 merge 函數:

x.data.frame <- data.frame(
  x = letters[1:6],
  foo.x = rnorm(6),
  bar.x = runif(6) > 0.5
)
x.data.frame
  x       foo.x bar.x
1 a -0.06067850  TRUE
2 b -0.01201291  TRUE
3 c -0.28666529 FALSE
4 d  1.64905115 FALSE
5 e -0.39324483  TRUE
6 f  0.25352265  TRUE
y.data.frame <- data.frame(
  foo.y = rnorm(6, 7, 9),
  bar.y = runif(6) < 0.5,
  x = letters[3:8]
)
y.data.frame
       foo.y bar.y x
1 -2.9982815  TRUE c
2 -0.1559176 FALSE d
3 12.6673980  TRUE e
4  6.6994744  TRUE f
5  0.3809737 FALSE g
6  3.3026685 FALSE h

使用 mergex.data.framey.data.frame 依據 x 欄位結合:

merge(x.data.frame, y.data.frame, by = "x")
  x      foo.x bar.x      foo.y bar.y
1 c -0.2866653 FALSE -2.9982815  TRUE
2 d  1.6490511 FALSE -0.1559176 FALSE
3 e -0.3932448  TRUE 12.6673980  TRUE
4 f  0.2535227  TRUE  6.6994744  TRUE

在使用 merge 合併 data frames 時,如果有些 x 欄位的值只出現在其中一個 data frame 中,而在另外一個 data frame 中找不到這個值的話,這一筆資料就會被忽略,如果需要將這樣不完全的資料也都保留的話,可以加上 all = TRUE 參數:

merge(x.data.frame, y.data.frame, by = "x", all = TRUE)
  x       foo.x bar.x      foo.y bar.y
1 a -0.06067850  TRUE         NA    NA
2 b -0.01201291  TRUE         NA    NA
3 c -0.28666529 FALSE -2.9982815  TRUE
4 d  1.64905115 FALSE -0.1559176 FALSE
5 e -0.39324483  TRUE 12.6673980  TRUE
6 f  0.25352265  TRUE  6.6994744  TRUE
7 g          NA    NA  0.3809737 FALSE
8 h          NA    NA  3.3026685 FALSE

對於含有數值資料的 data frame,我們可以使用 colSumscolMeans 函數來計算整個行的總和與平均:

colSums(x.data.frame[, 2:3])
   foo.x    bar.x 
1.149972 4.000000
colMeans(x.data.frame[, 2:3])
    foo.x     bar.x 
0.1916620 0.6666667

若要計算列的總和與平均,則可使用 rowSumsrowMeans 函數,用法都是類似的。