此前的 R 語言筆記參考 :
# R 語言安裝
# 在樹莓派上安裝 R 語言
# R 語言學習筆記 (一) : 基本語法與向量
# R 語言學習筆記 (二) : 矩陣
# R 語言學習筆記 (三) : 陣列
# R 語言學習筆記 (四) : 因子
資料框 (data.frame) 是 R 語言用來處理表格資料 (tabular data) 的資料型別, 也是其資料物件中最常用的一種, 它相當於 EXCEL 中的試算表 (sheet), 或者是 Pandas 的 DataFrmae 物件. 資料框與矩陣一樣是二維的資料結構, 具有直行 (或稱為欄) 與橫列兩個維度, 直行代表統計學中的變數 (variables), 橫列則代表觀測值 (observations), 在資料庫中直行代表欄位 (fields), 橫列稱為紀錄 (records).
資料框物件名稱 data.frame 中的句點乍看有物件導向意味, 但這其實是因為 R 早期版本不允許底線作為變數名稱 (因為底線當時用作指派), 因此許多物件名稱採用句點作為分隔或串接字元. 目前的 R 版本雖然已允許底線作為識別字名稱, 但使用句點串接仍是比較好的方式 (一致的風格), 參考 :
# R Variables and Constants
資料框的基本結構與矩陣一樣, 都是二維的資料結構, 每一行都是由長度相同的行向量組成, 它與矩陣或二維陣列不同之處主要有下列二個 :
- 資料框每一行可以是不同的資料型態; 而矩陣與陣列每個元素的型態必須相同.
- 資料框的行與列都有名稱; 而矩陣與陣列只有索引而無名稱.
操作資料框首先要建立 data.frame 物件 :
一. 建立 data.frame 物件的方法 :
1. 呼叫 data.frame() 函數 :
函數 data.frame() 的 API 如下 :
data.frame(..., row.names = NULL, check.rows = FALSE,
check.names = TRUE, fix.empty.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
詳細說明可在 R Console 中以 ?data.frame 指令查得.
參數列最前面的 ... 表示可以傳入長度相同的向量, 因子, 數值矩陣, 串列等資料物件. 例如可以將長度相同的一組向量當作參數傳入函數 data.frame() 來建立資料框物件 :
df <- dataframe(V1, V2, V3, ...)
例如 :
> v1 <- c("Kelly", "Peter", "Amy")
> v2 <- c("Female", "Male", "Female")
> v3 <- c(18, 16, 14)
> df1 <- data.frame(v1, v2, v3)
> df1
v1 v2 v3
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> class(df1)
[1] "data.frame" #物件類別是 data.frame
> typeof(df1)
[1] "list" #型態居然是 list
可見建立資料框時未指定行向量名稱, 預設會以行向量的程式變數名稱當作行向量的欄名 (即統計學中的觀測變數), 而列的名稱預設就是 1, 2, 3, .... 之連續數字. 因此, 資料框可視為一組相同長度行向量的組合, 組合不同資料結構形成資料框時, 必須注意資料長度是否相同, 例如上例若加入元素多一個的 married 向量就會出現錯誤 :
> v1 <- c("Kelly", "Peter", "Amy")
> v2 <- c("Female", "Male", "Female")
> v3 <- c(18, 16, 14)
> v4 <- c(FALSE, FALSE, FALSE, FALSE) #長度多 1 個> df1 <- data.frame(v1, v2, v3, v4)
> v2 <- c("Female", "Male", "Female")
> v3 <- c(18, 16, 14)
> v4 <- c(FALSE, FALSE, FALSE, FALSE) #長度多 1 個> df1 <- data.frame(v1, v2, v3, v4)
Error in data.frame(v1, v2, v3, v4) :
arguments imply differing number of rows: 3, 4
呼叫內建函數 View() 會開啟一個視窗以表格顯示資料框內容, 與 EXCEL 的試算表類似 :
> View(df1)
可見這是一個維度是 3*3 (3 列 3 行) 的資料框, 呼叫 dim(), nrow(), 以及 ncol() 函數會分別傳回資料框的維度, 列數, 以及行數, 例如 :
> dim(df1) #傳回維度
[1] 3 3 #3 列 3 行
> nrow(df1) #傳回列數
[1] 3
> ncol(df1) #傳回行數
[1] 3
在建立資料框時也可以指定欄位名稱, 這樣就不會使用預設之行向量名稱了, 例如 :
> df2 <- data.frame(name=v1, gender=v2, age=v3)
> df2
name gender age #指定之變數 (行向量) 名稱
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
可見指定欄位名稱後, 預設的欄名 (變數名稱) v1, v2, v3 就被 name, gender, age 取代了.
呼叫 str() 函數可觀察資料框結構, 每個 $ 符號後面就是欄位名稱, 然後跟著的是欄位元素之資料型別與內容 :
> str(df1)
'data.frame': 3 obs. of 3 variables:
$ v1: Factor w/ 3 levels "Amy","Kelly",..: 2 3 1
$ v2: Factor w/ 2 levels "Female","Male": 1 2 1
$ v3: num 18 16 14
> str(df2)
'data.frame': 3 obs. of 3 variables:
$ name : Factor w/ 3 levels "Amy","Kelly",..: 2 3 1
$ gender: Factor w/ 2 levels "Female","Male": 1 2 1
$ age : num 18 16 14
可見 df2 指定欄位名稱後與 df1 的預設欄名不同. 其次要注意的是, 若變數 (欄) 為文字向量, 則資料框預設會自動將其轉換為 Factor 因子變數, 例如上面 v1, v2 與 name, gender 變數後面顯示其為 Factor 向量. 如果要阻止自動轉換, 可在建立資料框時指定 stringAsFactor 參數為 FALSE 即可, 例如 :
> df1 <- data.frame(v1, v2, v3, stringAsFactor=FALSE)
> str(df1)
'data.frame': 3 obs. of 4 variables:
$ v1 : chr "Kelly" "Peter" "Amy"
$ v2 : chr "Female" "Male" "Female"
$ v3 : num 18 16 14
$ stringAsFactor: logi FALSE FALSE FALSE
可見 v1, v2 這兩個變數之資料型態獲得保留為字元 (chr). 呼叫 View() 函數顯示資料框結構時也會標示這個屬性值為 FALSE, 例如 :
呼叫 names() 或 colnames() 函數會傳回資料框的欄名, 呼叫 rownames() 則傳回列名, 例如 :
> names(df1)
[1] "v1" "v2" "v3"
> names(df2) #傳回欄位名稱
[1] "name" "gender" "age"
> colnames(df1) #傳回欄位名稱
[1] "v1" "v2" "v3"
> colnames(df2) #傳回欄位名稱
[1] "name" "gender" "age"
> rownames(df1) #傳回列名稱
[1] "1" "2" "3"
> rownames(df2) #傳回列名稱
[1] "1" "2" "3"
除了在建立資料框時指定欄位名稱外, 也可以利用內建函數 colnames() 透過向量索引改變欄位名稱, 例如 :
> df3 <- df1 #複製資料框 df1 至 df3
> df3
v1 v2 v3
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> colnames(df3)[c(1,2,3)] <- c("name", "gender", "age") #更改欄位 1, 2, 3 的名稱
> df3
name gender age #欄位名稱已被更改
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
以矩陣建立資料框時, 需注意每個矩陣之列數必須相同, 且須等於其他向量變數的長度, 例如下面的資料框 df4 由一個數值向量 v, 兩個矩陣 m1, m2, 以及一個布林向量 b 組成, 那麼它們的列長度必須一樣才行 :
> v <- c(9:10) #向量 (2 列)
> m1 <- matrix(1:6, nrow=2) #矩陣 (2 列)
> m2 <- matrix(7:12, nrow=2) #矩陣 (2 列)
> b <- c(TRUE, FALSE) #向量 (2 列)
> df4 <- data.frame(v, m1, m2, b)
> df4
v X1 X2 X3 X1.1 X2.1 X3.1 b
1 9 1 3 5 7 9 11 TRUE
2 10 2 4 6 8 10 12 FALSE
矩陣匯入到資料框時會將矩陣的各行 (欄) 轉成資料框的變數, 預設會將矩陣的每一行以 "X" 開頭依序命名, 例如 X1, X2, X3, ... 第二個矩陣為 X1.1, X2.1, X3.1, ... 等等, 呼叫 str() 可觀察其資料結構 :
> class(df4)
[1] "data.frame"
> str(df4)
'data.frame': 2 obs. of 8 variables:
$ v : int 9 10
$ X1 : int 1 2
$ X2 : int 3 4
$ X3 : int 5 6
$ X1.1: int 7 8
$ X2.1: int 9 10
$ X3.1: int 11 12
$ b : logi TRUE FALSE
> colnames(df4) #傳回資料框欄名向量
[1] "v" "X1" "X2" "X3" "X1.1" "X2.1" "X3.1" "b"
> df2 <- data.frame(name=v1, gender=v2, age=v3)
> df2
name gender age #指定之變數 (行向量) 名稱
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
可見指定欄位名稱後, 預設的欄名 (變數名稱) v1, v2, v3 就被 name, gender, age 取代了.
呼叫 str() 函數可觀察資料框結構, 每個 $ 符號後面就是欄位名稱, 然後跟著的是欄位元素之資料型別與內容 :
> str(df1)
'data.frame': 3 obs. of 3 variables:
$ v1: Factor w/ 3 levels "Amy","Kelly",..: 2 3 1
$ v2: Factor w/ 2 levels "Female","Male": 1 2 1
$ v3: num 18 16 14
> str(df2)
'data.frame': 3 obs. of 3 variables:
$ name : Factor w/ 3 levels "Amy","Kelly",..: 2 3 1
$ gender: Factor w/ 2 levels "Female","Male": 1 2 1
$ age : num 18 16 14
可見 df2 指定欄位名稱後與 df1 的預設欄名不同. 其次要注意的是, 若變數 (欄) 為文字向量, 則資料框預設會自動將其轉換為 Factor 因子變數, 例如上面 v1, v2 與 name, gender 變數後面顯示其為 Factor 向量. 如果要阻止自動轉換, 可在建立資料框時指定 stringAsFactor 參數為 FALSE 即可, 例如 :
> df1 <- data.frame(v1, v2, v3, stringAsFactor=FALSE)
> str(df1)
'data.frame': 3 obs. of 4 variables:
$ v1 : chr "Kelly" "Peter" "Amy"
$ v2 : chr "Female" "Male" "Female"
$ v3 : num 18 16 14
$ stringAsFactor: logi FALSE FALSE FALSE
呼叫 names() 或 colnames() 函數會傳回資料框的欄名, 呼叫 rownames() 則傳回列名, 例如 :
> names(df1)
[1] "v1" "v2" "v3"
> names(df2) #傳回欄位名稱
[1] "name" "gender" "age"
> colnames(df1) #傳回欄位名稱
[1] "v1" "v2" "v3"
> colnames(df2) #傳回欄位名稱
[1] "name" "gender" "age"
> rownames(df1) #傳回列名稱
[1] "1" "2" "3"
> rownames(df2) #傳回列名稱
[1] "1" "2" "3"
除了在建立資料框時指定欄位名稱外, 也可以利用內建函數 colnames() 透過向量索引改變欄位名稱, 例如 :
> df3 <- df1 #複製資料框 df1 至 df3
> df3
v1 v2 v3
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> colnames(df3)[c(1,2,3)] <- c("name", "gender", "age") #更改欄位 1, 2, 3 的名稱
> df3
name gender age #欄位名稱已被更改
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
同樣地, 也可以利用 colnames() 函數更改列名稱, 例如 :
> rownames(df3)[c(1,2,3)] <- c("R1", "R2", "R3") #更改列索引 1, 2, 3 的名稱
> df3
name gender age
R1 Kelly Female 18
R2 Peter Male 16
R3 Amy Female 14
> v <- c(9:10) #向量 (2 列)
> m1 <- matrix(1:6, nrow=2) #矩陣 (2 列)
> m2 <- matrix(7:12, nrow=2) #矩陣 (2 列)
> b <- c(TRUE, FALSE) #向量 (2 列)
> df4 <- data.frame(v, m1, m2, b)
> df4
v X1 X2 X3 X1.1 X2.1 X3.1 b
1 9 1 3 5 7 9 11 TRUE
2 10 2 4 6 8 10 12 FALSE
矩陣匯入到資料框時會將矩陣的各行 (欄) 轉成資料框的變數, 預設會將矩陣的每一行以 "X" 開頭依序命名, 例如 X1, X2, X3, ... 第二個矩陣為 X1.1, X2.1, X3.1, ... 等等, 呼叫 str() 可觀察其資料結構 :
> class(df4)
[1] "data.frame"
> str(df4)
'data.frame': 2 obs. of 8 variables:
$ v : int 9 10
$ X1 : int 1 2
$ X2 : int 3 4
$ X3 : int 5 6
$ X1.1: int 7 8
$ X2.1: int 9 10
$ X3.1: int 11 12
$ b : logi TRUE FALSE
> colnames(df4) #傳回資料框欄名向量
[1] "v" "X1" "X2" "X3" "X1.1" "X2.1" "X3.1" "b"
可見第一個矩陣 m1 的三行依序被命名為 X1, X2, X3; 而矩陣 m2 的三行則依序被命名為 X1.1, X2.1, 與 X3.1 等等.
2. 呼叫 as.dataframe() 建立資料框物件 :
資料框的資料來源可以是儲存於串列中的向量, 這時可呼叫 as.data.frame() 函數將串列轉成資料框, 例如 :
> v1 <- c("Kelly", "Peter", "Amy")
> v2 <- c("Female", "Male", "Female")
> v3 <- c(18, 16, 14)
> lst <- list(name=v1, gender=v2, age=v3)
> df5 <- as.data.frame(lst) #將串列轉成資料框
> class(df5)
[1] "data.frame"
> df5
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
可見串列中的每一項相當於一個行向量, 而 as.data.frame() 會將串列轉成資料框, 串列中的 key 成為欄名 (即變數).
3. 呼叫 do.call() 建立資料框物件 :
如果資料來源不是以行向量呈現, 而是儲存在串列中觀測值 (列資料), 每一筆的觀測值以單列資料框儲存於列表中, 則可利用 do.call() 函數呼叫 rbind() 來將這些列資料組合成資料框, 例如 :
> ob1 <- data.frame(c("Kelly"), c("Female"), c(18))
> ob2 <- data.frame(name=c("Peter"), gender=c("Male"), age=c(16))
> ob3 <- data.frame(name=c("Amy"), gender=c("Female"), age=c(14))
> df6 <- do.call(rbind, list(ob1, ob2, ob3))
> class(df6)
[1] "data.frame"
> df6
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
二. 存取資料框元素 :
存取資料框的內容有兩種方式 :
- 使用中括號 [列索引, 行索引] 存取整列, 整行, 或某行某列元素
- 使用 $行名 存取整欄 (行)
- 使用雙重中括號 [[行索引]]
1. 使用中括號 [列, 行] 存取 :
此種方式可以存取整行, 整列, 或指定儲存格元素, 例如 :
> df2
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> df2[1,] #取得第 1 列
name gender age
1 Kelly Female 18
> df2[2,] #取得第 2 列
name gender age
2 Peter Male 16
> df2[3,] #取得第 1 列
name gender age
3 Amy Female 14
> df2[, 1] #取得第 1 行
[1] "Kelly" "Peter" "Amy"
> df2[, 2] #取得第 2 行
[1] "Female" "Male" "Female"
> df2[, 3] #取得第 3 行
[1] 18 16 14
> df2[1, 1] #取得第 1 列第 1 行
[1] "Kelly"
> df2[2, 2] #取得第 2 列第 2 行
[1] "Male"
> df2[3, 3] #取得第 3 列第 3 行
[1] 14
2. 使用 $行名 存取 :
此種方式可存取整行之變數資料 :
> df2
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> df1$v1 #取得名稱為 v1 之變數 (整行)
[1] "Kelly" "Peter" "Amy"
> df1$v2 #取得名稱為 v2 之變數 (整行)
[1] "Female" "Male" "Female"
> df1$v3 #取得名稱為 v3 之變數 (整行)
[1] 18 16 14
3. 使用雙重中括號 [[行索引]] :
此種方式也是可存取整行之變數資料, 但使用是行索引來定位 :
> df2
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> df1[[1]] #取得第 1 行整行變數
[1] "Kelly" "Peter" "Amy"
> df1[[2]] #取得第 2 行整行變數
[1] "Female" "Male" "Female"
> df1[[3]] #取得第 3 行整行變數
[1] 18 16 14
下面是利用賦值運算符改變資料框內容的範例 :
> df2
name gender age
1 Kelly Female 18
2 Peter Male 16
3 Amy Female 14
> df2[1, 3] <- 19
> df2
name gender age
1 Kelly Female 19
2 Peter Male 16
3 Amy Female 14
> df2[, 3] <- c(20, 18, 16)
> df2
name gender age
1 Kelly Female 20
2 Peter Male 18
3 Amy Female 16
> df2[3, ] <- c("Tony", "Male", 55)
> df2
name gender age
1 Kelly Female 20
2 Peter Male 18
3 Tony Male 55
> df2$age <- c(21, 19, 56)
> df2
name gender age
1 Kelly Female 21
2 Peter Male 19
3 Tony Male 56
三. 資料框常用函數 :
上面所使用之資料框函數如下表 :
data.frame 常用函數 | 說明 |
data.frame(v1, v2, ...) | 將行向量 v1, v2, ... 組合資料框物件 |
names(df) | 傳回資料框 df 的行名 (欄, 變數名) |
rownames(df) | 傳回資料框 df 的列名 |
str(x) | 顯示物件結構與內容 |
length(x) | 顯示陣列元素個數 |
dim(x) | 顯示物件 (矩陣, 陣列, 資料框) 維度 : 列, 欄 |
nrow(df) | 傳回資料框 df 之列數 |
ncol(df) | 傳回資料框 df 之行 (欄) 數 |
參考 :
# R 語言基礎
沒有留言:
張貼留言