# R 語言安裝
# 在樹莓派上安裝 R 語言
# R 語言學習筆記 (一) : 基本語法與向量
# R 語言學習筆記 (二) : 矩陣
# R 語言學習筆記 (三) : 陣列
因子是 R 語言中用來儲存類型變數 (Categorical) 的資料結構. 統計學將變數區分為如下四種 :
類型 | 說明 | 範例 |
名義變數 | 只區別名稱, 無順序之分, 無法排序的變數 | 男女, 優劣, 晴陰雨 |
順序變數 | 有排序意義的變數 | 名次, 歌曲排行榜 |
離散變數 | 以整數為計數單位的變數, 其差距有意義 | 每周外食次數 |
連續變數 | 可連續取值之變數 | 身高, 體重 |
其中名義型變數與順序型變數具有可分類或可分級概念, 又稱為類型資料 (Categorical Data), 在 R 語言是以 factor (因子, 等級) 資料結構來儲存, 其中可排序的稱為有序因子 (ordered factor). 因子在 R 語言中是一種特殊的向量類型, 其內容之資料類型是一組表示名義或順序屬性的數值與字串, 例如 "男", "女" 或 1, 2, 3 等.
一. 建立因子物件的方法 :
1. 呼叫 factor() 函數 :
factor() 的 API 如下 :
factor(x = character(), levels, labels = levels,
exclude = NA, ordered = is.ordered(x), nmax = NA)
其中 :
x=向量 (通常是表示名義變數的字串或數值向量)
levels=設定之因子等級 (通常是字串或數值向量)
labels=因子數值加上標籤 (預設為 levels)
exclude=要排除的因子等級 (預設 NA 不排除)
ordered=因子是有序或無序 (預設 FALSE 無序)
nmax=因子等級最大值 (預設 NA 無最大值)
其中最主要的是前兩個參數, 即向量 x 與因子 levels (等級).
傳入向量 x, factor() 可將其轉換成因子. 例如 :
> grade1 <- c("A","B","A","C","B")
> fac1 <- factor(grade1)
> fac1
[1] A B A C B
Levels: A B C #因子等級為不重複之元素 (沒有雙引號)
可見顯示因子變數時, 不僅會顯示內容, 還會顯示這些元素的 "等級 (Level)", 即不重複的部分. 這些等級 (level) 預設是以字母順序排列的, 因子與向量不同之處是因子會將元素分群 (grouping), 相同的元素在一群就是一個因子, 因子用來儲存元素的類別 (Category).
用 class() 檢查因子變數可知其資料結構為 factor, 用 mode() 檢查其資料型態卻是 numeric, 這表示 Levels 的資料型態是數值, 雖然 Levels 看起來像是字串, 但實際上 R 語言內部是用整數索引來代表元素之值與等級, 可用 as.numeric() 或 as.integer() 函數得知.
> class(grade1)
[1] "character"
> mode(grade1) #字串向量元素資料型態為 character
[1] "character"
> class(fac1) #因子之資料結構為 factor
[1] "factor"
> mode(fac1)
[1] "numeric" #因子等級其實是用整數索引儲存的
呼叫 str() 會顯示因子變數之結構, 可印證因子元素都是以整數索引儲存 :
> fac1 <- factor(c("A","B","A","C","B"))
> str(fac1)
Factor w/ 3 levels "A","B","C": 1 2 1 3 2
可見等級 A, B, C 分別以 1, 2, 3 儲存, 因此因子變數之元素在內部實際上是儲存索引值 1 2 1 3 2.
由於因子變數之值通常是數值, 字串, 或布林值, 因此可呼叫 as.charactor(), as.numeric(), 與 as.logical() 將因子變數分別轉成字串向量, 數值向量, 或布林向量, 例如 :
> fac1 <- factor(c("A","B","A","C","B"))
> fac1
[1] A B A C B
Levels: A B C
> as.character(fac1)
[1] "A" "B" "A" "C" "B"
> as.integer(fac1)
[1] 1 2 1 3 2
> as.logical(fac1)
[1] NA NA NA NA NA #因 "A", "B", "C" 不是布林值
> as.logical(factor(c("TRUE","FALSE")))
[1] TRUE FALSE
> scores <- factor(c(78,99,67,56,100,23))
> scores
[1] 78 99 67 56 100 23
Levels: 23 56 67 78 99 100
> str(scores)
Factor w/ 6 levels "23","56","67",..: 4 5 3 2 6 1
> as.numeric(scores)
[1] 4 5 3 2 6 1
可見將因子用 as.numeric() 轉回數值向量時, 傳回的是因子變數內部代表元素的 1, 2, 3, 4, 5 索引值, 而非原始的成績. 這時可先呼叫 as.character() 再呼叫 as.numeric 來避免運算上的錯誤, 因為 as.charactor() 會傳回因子變數元素值之字串向量, 而非元素索引之字串向量 :
> as.character(scores) #as.character() 會傳回元素之字串向量
[1] "78" "99" "67" "56" "100" "23"
> as.numeric(as.character(scores)) #先呼叫 as.character() 轉成字串向量
[1] 78 99 67 56 100 23
可見傳回的是原始成績之數值向量而不是 1, 2, 3 ... 的索引了.
factor() 函數的第二參數 levels 用來列舉因子變數有哪些的等級. 雖然 factor() 會從元素的分群中自動找出因子的等級, 但當收集的數據不完整時, 等級 (Levels) 就會有缺漏, 例如 :
> seasons <-c("Spring", "Winter", "Spring", "Summer")
> fac2 <- factor(seasons)
> fac2
[1] Spring Winter Spring Summer
Levels: Spring Summer Winter #等級按照字母順序排列
> fac3 <- factor(seasons, levels=c("Winter","Fall","Summer","Spring"))
> fac3
[1] Spring Winter Spring Summer
Levels: Winter Fall Summer Spring #等級按照 levels 參數指定之順序排列
> ordered(c("A","B","A","C","B"),levels=c("C","B"))
[1] <NA> B <NA> C B
Levels: C < B
呼叫 levels() 函數會傳回一個字串向量, 其元素為因子變數的全部等級. 注意, 即使等級是數值, levels() 也是傳回字串向量, 例如 :
> fac4 <- factor(c("A","B","B","C")) #元素為字串
> fac4
[1] A B B C
Levels: A B C #沒有雙引號
> fac5 <- factor(c(1,2,2,3)) #元素為數值
> fac5
[1] 1 2 2 3
Levels: 1 2 3 #沒有雙引號
> levels(fac4)
[1] "A" "B" "C"
> levels(fac5)
[1] "1" "2" "3" #有雙引號 : levels() 一律傳回字串向量
函數 nlevels() 則會傳回因子有幾個等級, 例如 :
> grade1 <- c("A","B","A","C","B")
> fac1 <- factor(grade1)
> fac1
[1] A B A C B
Levels: A B C
> nlevels(fac1) #傳回因子等級數目
[1] 3 #含有 A, B, C 三個等級
factor() 函數預設使用元素本身作為等級之值, 參數 labels 可搭配 levels 參數來變更因子的顯示標籤, 例如以 "E", "W", "S", "N" 縮寫來代替 "EAST", "WEST", "SOUTH", "NORTH" :
> fac6 <- factor(directions,levels=c("EAST","WEST","SOUTH","NORTH"),labels=c("E", "W", "S", "N"))
> fac6
[1] E W S N W N
Levels: E W S N
可見不論元素或等級之值都被對應之 label 所取代了. 如果 labels 不是對應 levels 的字串向量, 而是單一字串, 則會以該字串冠上元素的等級數值作為新的元素與等級, 例如 :
>directions <- c("EAST", "WEST", "SOUTH", "NORTH", "WEST", "NORTH")
> fac7 <- factor(directions)
> str(fac7)
Factor w/ 4 levels "EAST","NORTH",..: 1 4 3 2 4 2
> fac8 <- factor(directions, labels="d") #會冠在等級數值前面
> str(fac8)Factor w/ 4 levels "d1","d2","d3",..: 1 4 3 2 4 2
> fac8
[1] d1 d4 d3 d2 d4 d2 #元素被改掉了
Levels: d1 d2 d3 d4 #等級也被改掉了
呼叫 tables() 函數會傳回一個 table 物件, 顯示各個等級的次數統計, 例如 :
> fac1 <- factor(c("A","B","A","C","B"))
> table(fac1)
fac1
A B C
2 2 1 #levels 的等級統計
> class(table(fac1))
[1] "table" #傳回 table 物件
> str(table(fac1))
'table' int [1:3(1d)] 2 2 1
- attr(*, "dimnames")=List of 1
..$ fac1: chr [1:3] "A" "B" "C"
傳回的 table 物件可以用索引存取, 例如 :
> tab1 <- table(fac1)
> tab1[1] #以索引存取 table 物件
A
2
> tab1[1] == 2
A
TRUE
factor() 的 ordered 參數預設為 FALSE, 表示預設建立無序因子, 若設為 TRUE 表示所建立的因子是有序的, 例如 :
> fac1 <- factor(c("A","B","B","C"))
> fac1
[1] A B B C
Levels: A B C
> fac7 <- factor(c("A","B","B","C"), ordered=TRUE) #有序因子
> fac7
[1] A B B C
Levels: A < B < C #等級是有順序的
可見有序因子的等級 (levels) 是照字母順序排序的.
2. 呼叫 as.factor() :
除了用 factor() 建立因子外, 也可以用 as.factor() 函數將向量轉成因子, 例如 :
> grade1 <- c("A","B","A","C","B")
> fac1 <- factor(grade1)
> fac1
[1] A B A C B
Levels: A B C
> fac2 <- as.factor(grade1)
> fac2
[1] A B A C B
Levels: A B C
> class(fac2)
[1] "factor"
> identical(fac1, fac2) #比較是否為相同物件
[1] TRUE
用 identical() 函數比較可知, 用 factor() 與 as.factor() 所建立之因子物件是雷同的 (結構與內容都一樣). 由於因子的元素通常為字串, 數值, 或布林, 因此可以用 as.character() 將因子物件轉型為字串向量, 用 as.integer() 與 as.numeric() 函數將因子物件轉為數值向量, 或用 as.logical() 轉成布林向量, 例如 :
> grade2 <- as.character(fac1)
> grade2
[1] "A" "B" "A" "C" "B"
> identical(grade1, grade2)
[1] TRUE
> grade3 <- as.numeric(fac1)
> grade3
[1] 1 2 1 3 2
> grade4 <- as.integer(fac1)
> grade4
[1] 1 2 1 3 2
2. 呼叫 ordered() 建立有序因子 (ordered factor) :
有序的類別型資料 (即統計學中的順序變數) 可用有序因子處理, 此函數 API 如下 :
ordered(x, ...)
其中參數 x 為原生向量 (數值, 字串, 布林等), 其餘參數 ... 與 factor() 參數一樣. 例如 :
> ordered(c("A","B","A","C","B"))
[1] A B A C B
Levels: A < B < C #等級按字母順序升序排列
> ordered(c("A","B","A","C","B"),levels=c("C","B","A")) #指定等級序列
[1] A B A C B
Levels: C < B < A #按 levels 參數指定之等級排序
> ordered(c(1,2,1,3,2))
[1] 1 2 1 3 2
Levels: 1 < 2 < 3
> ordered(c(TRUE,FALSE,TRUE,TRUE,FALSE))
[1] TRUE FALSE TRUE TRUE FALSE
Levels: FALSE < TRUE
可見有序因子的等級與一般因子不同之處在於多了方向標誌 "<", 若沒有用 levels 參數指定等級順序, 預設為按字母排列. 呼叫 class() 可以看出有序因子多了 "ordered" :
> class(ordered(c(1,2,1,3,2)))
[1] "ordered" "factor" #物件類型為有序因子
> class(factor(c(1,2,1,3,2)))
[1] "factor" #物件類型為一般因子
事實上, 這與呼叫 factor() 時使用 ordered=TRUE 參數建立之因子變數是完全一樣的, 例如 :
> fac3 <- ordered(c("A","B","A","C","B"))
> fac3
[1] A B A C B
Levels: A < B < C
> fac4 <- factor(c("A","B","A","C","B"), ordered=TRUE)
> fac4
[1] A B A C B
Levels: A < B < C
> identical(fac3, fac4)
[1] TRUE
二. 存取因子變數 :
因子變數其實就是添加了等級屬性的向量物件, 存取元素之方法與向量一樣都是使用索引 [], 例如 :
> fac1 <- factor(c("A","B","A","C","B"))
> fac1
[1] A B A C B
Levels: A B C
> fac1[1]
[1] A
Levels: A B C
> fac1[5]
[1] B
Levels: A B C
> fac1[2:4]
[1] B A C
Levels: A B C
更改因子變數之元素值, 所賦予之值必須在等級 (levels) 範圍內, 否則會出現錯誤, 例如 :
> fac1[1] <- c("K") #以 "K" 替換第一元素失敗 : 不在等級範圍內
Warning message:
In `[<-.factor`(`*tmp*`, 1, value = "K") :
invalid factor level, NA generated
> fac1[1] <- c("C") #第一元素改為 "C"
> fac1
[1] C B A C B
Levels: A B C
函數 levels() 會將因子之等級以向量傳回, 因此也可用 [] 索引來存取因子等級 :
> fac1 <- factor(c("A","B","A","C","B"))
> levels(fac1) #傳回因子變數之全部等級
[1] "A" "B" "C"
> class(levels(fac1)) #levels() 傳回字串向量
[1] "character"
> levels(fac1)[1] #顯示指定之等級分量
[1] "A"> levels(fac1)[2]
[1] "B"
> levels(fac1)[3]
[1] "C"
> levels(fac1)[1] <- c("D") #改變因子等級
> fac1
[1] D B D C B #等級 A 被改成 D 了
Levels: D B C
三. 因子常用函數 :
因子變數常用函數整理如下表 :
函數 | 說明 |
factor(x, levels, ...) | 將向量 x 轉型為因子物件 |
gl(n, k) | 建立一個含有 k 個等級 |
str(x) | 顯示物件結構與內容 |
length(x) | 顯示陣列元素個數 |
dim(x) | 顯示物件 (矩陣, 陣列, 資料框) 維度 |
is.factor(x) | 檢查是否為因子類型 |
as.factor(x) | 將向量轉型為因子類型 |
as.numeric(x) | 將因子轉型為數值類型 |
as.integer(x) | 將因子轉型為整數類型 |
as.charactor(x) | 將因子轉型為字串類型 |
identical(x, y) | 檢查兩個物件 x, y 是否為相同物件 |
levels(x) | 傳回因子 x 之水平 (等級) 向量 |
nlevels(x) | 傳回因子 x 之水平 (等級) 數量 |
謝謝 最後兩個常用函數的解釋"水平" 看不懂? 是等級嗎?
回覆刪除嗨, 柳丁, LEVEL 應該是譯為等級較妥, 水平一詞來自手邊幾本中文書, 譯者大概認為不同之等級一如不同之水平, 且與原文字面意思較近, 故也就沿用了.
回覆刪除感恩!
回覆刪除