6 資料處理與清洗
6.1 Tidy Data
Each column is a variable. Each row is an observation.
- 一個欄位(Column)內只有一個數值,最好要有凡人看得懂的Column Name
- 不同的觀察值應該要在不同列(Row)
- 一張表裡面,有所有分析需要的資料
- 如果一定要多張表,中間一定要有index可以把表串起來
- One file, one table
6.2 資料型別轉換處理
在資料型態章節Chapter 1.5中,曾介紹數值 (numeric)、字串 (character)、布林變數 (logic)以及日期 (Date)等資料型態,在此章節中將介紹如何檢查變數型別與各型別的轉換。
6.2.1 資料型別檢查
使用以下is.
函數檢查資料型別,回傳布林變數,若為真,回傳TRUE
- 是否為數字
is.numeric(變數名稱)
- 是否為文字
is.character(變數名稱)
- 是否為布林變數
is.logical(變數名稱)
## [1] TRUE
## [1] FALSE
## [1] FALSE
## [1] TRUE
## [1] TRUE
或使用class(變數名稱)
函數,直接回傳資料型別
## [1] "numeric"
## [1] "character"
## [1] "logical"
## [1] "Date"
6.2.2 資料型別轉換
使用以下as.
函數轉換型別
- 轉換為數字
as.numeric(變數名稱)
- 轉換為文字
as.character(變數名稱)
- 轉換為布林變數
as.logical(變數名稱)
## [1] 200
## [1] 1
## [1] "100"
## [1] "TRUE"
若無法順利完成轉換,會回傳空值NA
,並出現警告訊息Warning: NAs introduced by coercion,Warning: 強制變更過程中產生了 NA
## Warning: 強制變更過程中產生了 NA
## [1] NA
日期的轉換則建議使用lubridate
(Spinu, Grolemund, and Wickham 2020) package,如果想要將年/月/日
格式的文字轉換為日期物件,可使用ymd()
函數(y表年year,m表月month,d表日day),如果想要將月/日/年
格式的文字轉換為日期物件,則使用mdy()
函數,以此類推。
## [1] "2012-03-03"
## [1] "2012-03-03"
6.3 文字字串處理
6.3.1 基本處理
- 切割
strsplit()
- 子集
substr()
- 大小寫轉換
toupper()
tolower()
- 兩文字連接
paste()
paste0()
- 文字取代
gsub()
- 前後空白去除
str_trim()
需安裝stringr
(Wickham 2019b) package
## [[1]]
## [1] "Hello" "World"
## [1] "HELLO WORLD"
## [1] "hello world"
## [1] "HelloWorld"
## [1] "ell"
## [1] "Hell0 W0rld"
## [1] "Hello World"
6.3.2 搜尋字串
搜尋字串函數通常使用在比對文字向量,文字比對有分大小寫,依照回傳值的型態不同,有兩種常用函數,grep()
與grepl()
:
- 回傳符合條件之向量位置(index)
grep(搜尋條件,要搜尋的向量)
- 回傳每個向量是否符合條件(TRUE or FALSE)
grepl(搜尋條件,要搜尋的向量)
## [1] 1 3
## [1] TRUE FALSE TRUE FALSE FALSE
## [1] FALSE FALSE FALSE FALSE TRUE
6.3.3 正規表示式 (Regular Expression)
字串處理通常會搭配正規表示式 (Regular Expression)
Regular Expression (正規表示式)是指一組能用來表示字串共同格式 (common structure)的樣式 (Pattern),像是@
符號會固定出現在email中,或是手機號碼固定是10碼,等等樣式。
在所有的程式語言中,只要用到字串比對與字串取代等字串相關功能,都會用到正規表示式。雖然正規表示式在不同程式語言中會有些許差異,但核心概念是相同的。
以下是常見的範例:
語法 | 正則表達式 | 範例 |
---|---|---|
整數 | [0-9]+ | 5815 |
浮點數 | [0-9]+.[0-9]+ | 58.15 |
純英文字串 | [A-Za-z]+ | CGUIM |
[a-zA-Z0-9_]+@[a-zA-Z0-9._]+ | im@mail.cgu.edu.tw |
|
URL | http://[a-zA-Z0-9./_]+ |
http://www.is.cgu.edu.tw/ |
可以用正規表示式的R函數如下:
- grep()
- grepl()
- gsub()
- str_split()
- stringr package中的諸多函數
正規表示式的常用語法分類如下:
- 逃脫字元
- 表示數量
- 表示位置
- 運算子
- 特殊符號
6.3.3.1 逃脫字元
****
6.3.3.2 表示數量的語法
*
: 出現0~無限多次+
: 出現1~無限多次?
: 出現0~1次{n}
: 出現n次{n,}
: 出現n~無限多次{n,m}
: 出現n~m次
## [1] "a" "abc" "ac" "abbc" "abbbc" "abbbbc"
## [1] "abc" "abbc" "abbbc" "abbbbc"
## [1] "abc" "ac"
## [1] "abbc"
## [1] "abbc" "abbbc" "abbbbc"
## [1] "abbc" "abbbc"
6.3.3.3 表示位置的語法
^
: 出現在字串開始的位置$
: 出現在字串結束ˇ的位置\b
: 出現空字串(空白)開始或結束的位置\B
: 出現非字串開始或結束的位置
## [1] "bcd" "bcdefg abc"
## [1] "abc" "bcdefg abc"
## [1] "def" "abc def"
## [1] "cde" "bcdefg abc"
6.3.3.4 運算子
.
: 出現所有的字元一次,包括空字串[...]
: 出現字元清單(…)中的字元一次,可用-
表示範圍,如[A-Z]
,[a-z]
,[0-9]
[^...]
: 不出現字元清單(…)中的字元\
: 要搜尋字串中的特殊字元時,前方須加上\
|
: 或
stringVector<-c("03-2118800","02-23123456","0988123456",
"07-118","0-888","csim@mail.cgu.edu.tw","csim@.","csim@",
"http://www.is.cgu.edu.tw/")
grep("[0-9]{2}-[0-9]{7,8}",stringVector,value=T)
## [1] "03-2118800" "02-23123456"
## [1] "0988123456"
## [1] "03-2118800" "02-23123456"
## [1] "csim@mail.cgu.edu.tw" "csim@."
6.3.3.5 特殊符號
\d
: 數字,等於 [0-9]\D
: 非數字,等於 [^0-9][:lower:]
: 小寫字,等於 [a-z][:upper:]
: 大寫字,等於 [A-Z][:alpha:]
: 所有英文字,等於 [[:lower:][:upper:]] or [A-z][:alnum:]
: 所有英文字和數字,等於 [[:alpha:][:digit:]] or [A-z0-9]\w
: 文字數字與底線,等於 [[:alnum:]_] or [A-z0-9_]\W
: 非文字數字與底線,等於 [^A-z0-9_][:blank:]
: 空白字元,包括空白和tab\s
: 空白字元,\S
: 非空白字元[:punct:]
: 標點符號 ! " # $ % & ’ ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~.
stringVector<-c("03-2118800","02-23123456","0988123456",
"07-118","0-888","csim@mail.cgu.edu.tw","http://www.is.cgu.edu.tw/")
grep("\\d{2}-\\d{7,8}",stringVector,value=T)
## [1] "03-2118800" "02-23123456"
## [1] "0988123456"
## [1] "csim@mail.cgu.edu.tw"
6.3.3.6 參考資料
6.4 子集Subset
6.4.1 一維資料 (向量)
在向量章節{#vector}
有介紹使用[]
取出單一或多個元素的方法
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## [1] "a"
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
## [1] "a" "c" "e"
## [1] "b" "d" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v"
## [20] "w" "x" "y" "z"
若想要快速取得一向量的開頭與結尾元素,可使用head()
和tail()
函數
## [1] "a" "b" "c" "d" "e"
## [1] "x" "y" "z"
6.4.2 二維資料
最常見的二維資料為data.frame資料框,二維資料可針對列(Row)和行(Column)做子集,子集選擇方式一樣是使用[]
,但因應二維資料的需求,以,
分隔列與行的篩選條件,資料篩選原則為前Row,後Column,前列,後行,若不想篩選列,則在,
前方保持空白即可。
篩選方式可輸入位置(index)、欄位名稱或輸入布林變數(TRUE/FALSE)
- 輸入位置:
dataFrame[row index,column index]
- 輸入布林變數:
dataFrame[c(T,F,T),c(T,F,T)]
- 輸入欄位名稱:
dataFrame[row name,column name]
## [1] 3.5
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## [1] setosa setosa setosa setosa setosa setosa
## [7] setosa setosa setosa setosa setosa setosa
## [13] setosa setosa setosa setosa setosa setosa
## [19] setosa setosa setosa setosa setosa setosa
## [25] setosa setosa setosa setosa setosa setosa
## [31] setosa setosa setosa setosa setosa setosa
## [37] setosa setosa setosa setosa setosa setosa
## [43] setosa setosa setosa setosa setosa setosa
## [49] setosa setosa versicolor versicolor versicolor versicolor
## [55] versicolor versicolor versicolor versicolor versicolor versicolor
## [61] versicolor versicolor versicolor versicolor versicolor versicolor
## [67] versicolor versicolor versicolor versicolor versicolor versicolor
## [73] versicolor versicolor versicolor versicolor versicolor versicolor
## [79] versicolor versicolor versicolor versicolor versicolor versicolor
## [85] versicolor versicolor versicolor versicolor versicolor versicolor
## [91] versicolor versicolor versicolor versicolor versicolor versicolor
## [97] versicolor versicolor versicolor versicolor virginica virginica
## [103] virginica virginica virginica virginica virginica virginica
## [109] virginica virginica virginica virginica virginica virginica
## [115] virginica virginica virginica virginica virginica virginica
## [121] virginica virginica virginica virginica virginica virginica
## [127] virginica virginica virginica virginica virginica virginica
## [133] virginica virginica virginica virginica virginica virginica
## [139] virginica virginica virginica virginica virginica virginica
## [145] virginica virginica virginica virginica virginica virginica
## Levels: setosa versicolor virginica
## Sepal.Length Petal.Length Species
## 1 5.1 1.4 setosa
## 2 4.9 1.4 setosa
## 3 4.7 1.3 setosa
## 4 4.6 1.5 setosa
## 5 5.0 1.4 setosa
## 6 5.4 1.7 setosa
## 7 4.6 1.4 setosa
## 8 5.0 1.5 setosa
## 9 4.4 1.4 setosa
## 10 4.9 1.5 setosa
也可使用$
符號做Column的篩選
## [1] setosa setosa setosa setosa setosa setosa
## [7] setosa setosa setosa setosa setosa setosa
## [13] setosa setosa setosa setosa setosa setosa
## [19] setosa setosa setosa setosa setosa setosa
## [25] setosa setosa setosa setosa setosa setosa
## [31] setosa setosa setosa setosa setosa setosa
## [37] setosa setosa setosa setosa setosa setosa
## [43] setosa setosa setosa setosa setosa setosa
## [49] setosa setosa versicolor versicolor versicolor versicolor
## [55] versicolor versicolor versicolor versicolor versicolor versicolor
## [61] versicolor versicolor versicolor versicolor versicolor versicolor
## [67] versicolor versicolor versicolor versicolor versicolor versicolor
## [73] versicolor versicolor versicolor versicolor versicolor versicolor
## [79] versicolor versicolor versicolor versicolor versicolor versicolor
## [85] versicolor versicolor versicolor versicolor versicolor versicolor
## [91] versicolor versicolor versicolor versicolor versicolor versicolor
## [97] versicolor versicolor versicolor versicolor virginica virginica
## [103] virginica virginica virginica virginica virginica virginica
## [109] virginica virginica virginica virginica virginica virginica
## [115] virginica virginica virginica virginica virginica virginica
## [121] virginica virginica virginica virginica virginica virginica
## [127] virginica virginica virginica virginica virginica virginica
## [133] virginica virginica virginica virginica virginica virginica
## [139] virginica virginica virginica virginica virginica virginica
## [145] virginica virginica virginica virginica virginica virginica
## Levels: setosa versicolor virginica
Row的篩選可使用subset()
函數,使用方法為subset(資料表,篩選邏輯)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 101 6.3 3.3 6.0 2.5 virginica
## 102 5.8 2.7 5.1 1.9 virginica
## 103 7.1 3.0 5.9 2.1 virginica
## 104 6.3 2.9 5.6 1.8 virginica
## 105 6.5 3.0 5.8 2.2 virginica
## 106 7.6 3.0 6.6 2.1 virginica
## 107 4.9 2.5 4.5 1.7 virginica
## 108 7.3 2.9 6.3 1.8 virginica
## 109 6.7 2.5 5.8 1.8 virginica
## 110 7.2 3.6 6.1 2.5 virginica
## 111 6.5 3.2 5.1 2.0 virginica
## 112 6.4 2.7 5.3 1.9 virginica
## 113 6.8 3.0 5.5 2.1 virginica
## 114 5.7 2.5 5.0 2.0 virginica
## 115 5.8 2.8 5.1 2.4 virginica
## 116 6.4 3.2 5.3 2.3 virginica
## 117 6.5 3.0 5.5 1.8 virginica
## 118 7.7 3.8 6.7 2.2 virginica
## 119 7.7 2.6 6.9 2.3 virginica
## 120 6.0 2.2 5.0 1.5 virginica
## 121 6.9 3.2 5.7 2.3 virginica
## 122 5.6 2.8 4.9 2.0 virginica
## 123 7.7 2.8 6.7 2.0 virginica
## 124 6.3 2.7 4.9 1.8 virginica
## 125 6.7 3.3 5.7 2.1 virginica
## 126 7.2 3.2 6.0 1.8 virginica
## 127 6.2 2.8 4.8 1.8 virginica
## 128 6.1 3.0 4.9 1.8 virginica
## 129 6.4 2.8 5.6 2.1 virginica
## 130 7.2 3.0 5.8 1.6 virginica
## 131 7.4 2.8 6.1 1.9 virginica
## 132 7.9 3.8 6.4 2.0 virginica
## 133 6.4 2.8 5.6 2.2 virginica
## 134 6.3 2.8 5.1 1.5 virginica
## 135 6.1 2.6 5.6 1.4 virginica
## 136 7.7 3.0 6.1 2.3 virginica
## 137 6.3 3.4 5.6 2.4 virginica
## 138 6.4 3.1 5.5 1.8 virginica
## 139 6.0 3.0 4.8 1.8 virginica
## 140 6.9 3.1 5.4 2.1 virginica
## 141 6.7 3.1 5.6 2.4 virginica
## 142 6.9 3.1 5.1 2.3 virginica
## 143 5.8 2.7 5.1 1.9 virginica
## 144 6.8 3.2 5.9 2.3 virginica
## 145 6.7 3.3 5.7 2.5 virginica
## 146 6.7 3.0 5.2 2.3 virginica
## 147 6.3 2.5 5.0 1.9 virginica
## 148 6.5 3.0 5.2 2.0 virginica
## 149 6.2 3.4 5.4 2.3 virginica
## 150 5.9 3.0 5.1 1.8 virginica
Row的篩選也可搭配字串搜尋函數grepl()
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | |
---|---|---|---|---|---|
51 | 7.0 | 3.2 | 4.7 | 1.4 | versicolor |
52 | 6.4 | 3.2 | 4.5 | 1.5 | versicolor |
53 | 6.9 | 3.1 | 4.9 | 1.5 | versicolor |
54 | 5.5 | 2.3 | 4.0 | 1.3 | versicolor |
55 | 6.5 | 2.8 | 4.6 | 1.5 | versicolor |
56 | 5.7 | 2.8 | 4.5 | 1.3 | versicolor |
57 | 6.3 | 3.3 | 4.7 | 1.6 | versicolor |
58 | 4.9 | 2.4 | 3.3 | 1.0 | versicolor |
59 | 6.6 | 2.9 | 4.6 | 1.3 | versicolor |
60 | 5.2 | 2.7 | 3.9 | 1.4 | versicolor |
61 | 5.0 | 2.0 | 3.5 | 1.0 | versicolor |
62 | 5.9 | 3.0 | 4.2 | 1.5 | versicolor |
63 | 6.0 | 2.2 | 4.0 | 1.0 | versicolor |
64 | 6.1 | 2.9 | 4.7 | 1.4 | versicolor |
65 | 5.6 | 2.9 | 3.6 | 1.3 | versicolor |
66 | 6.7 | 3.1 | 4.4 | 1.4 | versicolor |
67 | 5.6 | 3.0 | 4.5 | 1.5 | versicolor |
68 | 5.8 | 2.7 | 4.1 | 1.0 | versicolor |
69 | 6.2 | 2.2 | 4.5 | 1.5 | versicolor |
70 | 5.6 | 2.5 | 3.9 | 1.1 | versicolor |
71 | 5.9 | 3.2 | 4.8 | 1.8 | versicolor |
72 | 6.1 | 2.8 | 4.0 | 1.3 | versicolor |
73 | 6.3 | 2.5 | 4.9 | 1.5 | versicolor |
74 | 6.1 | 2.8 | 4.7 | 1.2 | versicolor |
75 | 6.4 | 2.9 | 4.3 | 1.3 | versicolor |
76 | 6.6 | 3.0 | 4.4 | 1.4 | versicolor |
77 | 6.8 | 2.8 | 4.8 | 1.4 | versicolor |
78 | 6.7 | 3.0 | 5.0 | 1.7 | versicolor |
79 | 6.0 | 2.9 | 4.5 | 1.5 | versicolor |
80 | 5.7 | 2.6 | 3.5 | 1.0 | versicolor |
81 | 5.5 | 2.4 | 3.8 | 1.1 | versicolor |
82 | 5.5 | 2.4 | 3.7 | 1.0 | versicolor |
83 | 5.8 | 2.7 | 3.9 | 1.2 | versicolor |
84 | 6.0 | 2.7 | 5.1 | 1.6 | versicolor |
85 | 5.4 | 3.0 | 4.5 | 1.5 | versicolor |
86 | 6.0 | 3.4 | 4.5 | 1.6 | versicolor |
87 | 6.7 | 3.1 | 4.7 | 1.5 | versicolor |
88 | 6.3 | 2.3 | 4.4 | 1.3 | versicolor |
89 | 5.6 | 3.0 | 4.1 | 1.3 | versicolor |
90 | 5.5 | 2.5 | 4.0 | 1.3 | versicolor |
91 | 5.5 | 2.6 | 4.4 | 1.2 | versicolor |
92 | 6.1 | 3.0 | 4.6 | 1.4 | versicolor |
93 | 5.8 | 2.6 | 4.0 | 1.2 | versicolor |
94 | 5.0 | 2.3 | 3.3 | 1.0 | versicolor |
95 | 5.6 | 2.7 | 4.2 | 1.3 | versicolor |
96 | 5.7 | 3.0 | 4.2 | 1.2 | versicolor |
97 | 5.7 | 2.9 | 4.2 | 1.3 | versicolor |
98 | 6.2 | 2.9 | 4.3 | 1.3 | versicolor |
99 | 5.1 | 2.5 | 3.0 | 1.1 | versicolor |
100 | 5.7 | 2.8 | 4.1 | 1.3 | versicolor |
若想要快速取得資料框的前幾列(Row)或後幾列,也可使用head()
和tail()
函數
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 148 6.5 3.0 5.2 2.0 virginica
## 149 6.2 3.4 5.4 2.3 virginica
## 150 5.9 3.0 5.1 1.8 virginica
6.5 排序
6.5.1 sort 向量排序
sort()
函數可直接對向量做由小到大的排序
## Africa Antarctica Asia Australia Axel Heiberg Baffin
## 11506 5500 16988 2968 16 184
## Vancouver Hainan Prince of Wales Timor Kyushu
## 12 13 13 13 14
## Taiwan
## 14
如需由大到小排序,可將decreasing
參數設為TRUE
## Asia Africa North America South America Antarctica
## 16988 11506 9390 6795 5500
## Europe
## 3745
6.5.2 order
如需對資料框做排序,可使用order()
函數,order()
函數可回傳由小到大之元素位置,以iris$Sepal.Length
為例,回傳的第一個位置為14
,表示iris$Sepal.Length
中,數值最小的元素為第14個元素。
## [1] 14 9 39 43 42 4 7 23 48 3 30 12 13 25 31 46 2 10
## [19] 35 38 58 107 5 8 26 27 36 41 44 50 61 94 1 18 20 22
## [37] 24 40 45 47 99 28 29 33 60 49 6 11 17 21 32 85 34 37
## [55] 54 81 82 90 91 65 67 70 89 95 122 16 19 56 80 96 97 100
## [73] 114 15 68 83 93 102 115 143 62 71 150 63 79 84 86 120 139 64
## [91] 72 74 92 128 135 69 98 127 149 57 73 88 101 104 124 134 137 147
## [109] 52 75 112 116 129 133 138 55 105 111 117 148 59 76 66 78 87 109
## [127] 125 141 145 146 77 113 144 53 121 140 142 51 103 110 126 130 108 131
## [145] 106 118 119 123 136 132
## [1] 4.3
若將decreasing
參數設定為TRUE,則會回傳由大到小的元素位置,以iris$Sepal.Length
為例,回傳的第一個位置為132
,表示iris$Sepal.Length
中,數值最大的元素為第132個元素。
## [1] 132 118 119 123 136 106 131 108 110 126 130 103 51 53 121 140 142 77
## [19] 113 144 66 78 87 109 125 141 145 146 59 76 55 105 111 117 148 52
## [37] 75 112 116 129 133 138 57 73 88 101 104 124 134 137 147 69 98 127
## [55] 149 64 72 74 92 128 135 63 79 84 86 120 139 62 71 150 15 68
## [73] 83 93 102 115 143 16 19 56 80 96 97 100 114 65 67 70 89 95
## [91] 122 34 37 54 81 82 90 91 6 11 17 21 32 85 49 28 29 33
## [109] 60 1 18 20 22 24 40 45 47 99 5 8 26 27 36 41 44 50
## [127] 61 94 2 10 35 38 58 107 12 13 25 31 46 3 30 4 7 23
## [145] 48 42 9 39 43 14
## [1] 7.9
依照order回傳的元素位置,重新排序iris資料框
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 14 4.3 3.0 1.1 0.1 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 39 4.4 3.0 1.3 0.2 setosa
## 43 4.4 3.2 1.3 0.2 setosa
## 42 4.5 2.3 1.3 0.3 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 132 7.9 3.8 6.4 2.0 virginica
## 118 7.7 3.8 6.7 2.2 virginica
## 119 7.7 2.6 6.9 2.3 virginica
## 123 7.7 2.8 6.7 2.0 virginica
## 136 7.7 3.0 6.1 2.3 virginica
## 106 7.6 3.0 6.6 2.1 virginica
6.6 資料組合
有時需要在資料框新增一列,或新增一行,可以利用資料組合函數完成
- Row 列的組合
rbind()
- Column 行的組合
cbind()
rbind()
和cbind()
的參數可以是向量,也可以是資料框,使用向量做資料整合範例:
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
使用資料框與向量做資料整合範例:
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 146 6.7 3 5.2 2.3 virginica
## 147 6.3 2.5 5 1.9 virginica
## 148 6.5 3 5.2 2 virginica
## 149 6.2 3.4 5.4 2.3 virginica
## 150 5.9 3 5.1 1.8 virginica
## 151 1 1 1 1 versicolor
使用向量做資料整合範例:
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
使用資料框與向量做資料整合範例:
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 145 6.7 3.3 5.7 2.5 virginica
## 146 6.7 3.0 5.2 2.3 virginica
## 147 6.3 2.5 5.0 1.9 virginica
## 148 6.5 3.0 5.2 2.0 virginica
## 149 6.2 3.4 5.4 2.3 virginica
## 150 5.9 3.0 5.1 1.8 virginica
## rep("Add", nrow(iris))
## 145 Add
## 146 Add
## 147 Add
## 148 Add
## 149 Add
## 150 Add
6.7 資料結合 (Join)
除了按照行列順序的組合外,更常有的情形是依照某個欄位的值作為結合依據,如:
- 用學號把以下兩個資料框結合成一個資料框
- 學號與姓名資料框
- 學號與宿舍床位資料框
- 用縣市名稱與年度將人口資料與醫療資源資料結合
原生的R環境可以用merge()
函數將資料框結合,使用方法為merge(資料框1,資料框2,by="結合依據欄位")
nameDF<-data.frame(ID=c(1,2,3,4,5),
Name=c("Amy","Bob","Chris","David","Emma"))
scoreDF<-data.frame(ID=c(1,2,4),
Score=c(60,90,50))
ID | Name |
---|---|
1 | Amy |
2 | Bob |
3 | Chris |
4 | David |
5 | Emma |
ID | Score |
---|---|
1 | 60 |
2 | 90 |
4 | 50 |
ID | Name | Score |
---|---|---|
1 | Amy | 60 |
2 | Bob | 90 |
4 | David | 50 |
按照上述輸出結果可知,merge函數預設只保留兩資料框都有對應到的資料,如果不想要merge函數將沒對應到的資料刪除,可以設定參數all
,all.x
或是all.y
,來保留沒對應到的資料列。
merge(資料框1,資料框2,by="結合依據欄位",all=T)
merge(資料框1,資料框2,by="結合依據欄位",all.x=T)
merge(資料框1,資料框2,by="結合依據欄位",all.y=T)
ID | Name | Score |
---|---|---|
1 | Amy | 60 |
2 | Bob | 90 |
3 | Chris | NA |
4 | David | 50 |
5 | Emma | NA |
dplyr
套件提供更有效率的資料結合方法,包括:
- inner_join():保留有對應到的資料
- left_join():保留左邊資料框的所有資料
- right_join():保留右邊資料框的所有資料
- full_join():保留所有資料
- semi_join()
- anti_join()
inner_join():只保留兩張表都有的列,使用方法為 inner_join(x, y, by = )
## ID Name Score
## 1 1 Amy 60
## 2 2 Bob 90
## 3 4 David 50
left_join():保留左邊的表所有的列,使用方法文為 left_join(x, y, by = )
## ID Name Score
## 1 1 Amy 60
## 2 2 Bob 90
## 3 3 Chris NA
## 4 4 David 50
## 5 5 Emma NA
right_join():保留右邊的表所有的列。使用方法為 right_join(x, y, by = )
## ID Name Score
## 1 1 Amy 60
## 2 2 Bob 90
## 3 4 David 50
full_join():保留所有的列。使用方法為 full_join(x, y, by = )
## ID Name Score
## 1 1 Amy 60
## 2 2 Bob 90
## 3 3 Chris NA
## 4 4 David 50
## 5 5 Emma NA
semi_join():留下左邊的ID也有出現在右邊的表的列,右表資料不會輸出。使用方法為 semi_join(x, y, by = )
## ID Name
## 1 1 Amy
## 2 2 Bob
## 3 4 David
6.8 長表與寬表
在資料處理的過程中,常因各種需求,需要執行長寬表互換的動作,在R中有很好用的套件reshape2(Wickham 2020) package,提供完整的轉換功能,最常使用的是
- 寬表轉長表
melt(資料框/寬表,id.vars=需要保留的欄位)
- 長表轉寬表
dcast(資料框/長表,寬表分列依據~分欄位依據)
原來的airquality
資料框中,有Ozone, Solar.R, Wind, Temp, Month, Day等六個欄位 (Column),屬於寬表,以下範例將保留Month和Day兩個欄位,並將其他欄位的名稱整合至variable欄位,數值整合至value欄位,寬表轉長表範例如下:
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## Month Day variable value
## 1 5 1 Ozone 41
## 2 5 2 Ozone 36
## 3 5 3 Ozone 12
## 4 5 4 Ozone 18
## 5 5 5 Ozone NA
## 6 5 6 Ozone 28
轉換過的長表airqualityM
資料框中,剩下Month, Day, variable, value等四個欄位 (Column),屬於長表,以下範例variable欄位的值轉換為新欄位,並將value欄位填回新增的欄位,長表轉寬表範例如下:
library(reshape2)
##欄位保留"Month","Day"外,其他欄位數目由variable定義
airqualityCast<-dcast(airqualityM, Month +Day~variable)
head(airqualityCast)
## Month Day Ozone Solar.R Wind Temp
## 1 5 1 41 190 7.4 67
## 2 5 2 36 118 8.0 72
## 3 5 3 12 149 12.6 74
## 4 5 4 18 313 11.5 62
## 5 5 5 NA NA 14.3 56
## 6 5 6 28 NA 14.9 66
tidyverse套件組的tidyr (Wickham and Henry 2020) package,也提供完整的轉換功能,舉例如下
- 寬表轉長表
gather(資料框/寬表,key="主鍵欄位名稱",value="數值欄位名稱",要轉換的資料1,要轉換的資料2,...)
- 長表轉寬表
spread(資料框/長表,key="要展開的欄位名稱",value="數值欄位名稱")
同上,以airquality
資料框為例,原來的airquality
資料框中,有Ozone, Solar.R, Wind, Temp, Month, Day等六個欄位 (Column),屬於寬表
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
以下範例將保留Month和Day兩個欄位,將其他欄位的名稱整合至Type欄位,數值整合至Value欄位,寬表轉長表範例如下:
library(tidyr)
airqualityL<-gather(airquality,
key=Type,value=Value,
Ozone,Solar.R,Wind,Temp) ##欄位Ozone,Solar.R,Wind,Temp轉成單一欄位
轉換過的長表airqualityL
資料框中,剩下Month, Day, Type, Value等四個欄位 (Column),屬於長表,以下範例Type欄位的值轉換為新欄位,並將Value欄位填回新增的欄位,長表轉寬表範例如下:
#欄位保留"Month","Day"外,其他欄位由variable定義
airqualityW<-spread(airqualityL, key=Type,value=Value)
head(airqualityW)
## Month Day Ozone Solar.R Temp Wind
## 1 5 1 41 190 67 7.4
## 2 5 2 36 118 72 8.0
## 3 5 3 12 149 74 12.6
## 4 5 4 18 313 62 11.5
## 5 5 5 NA NA 56 14.3
## 6 5 6 28 NA 66 14.9
6.9 遺漏值處理
遺漏值(Missing Value)常常出現在真實資料內,在數值運算時常會有問題,最簡單的方法是將有缺值的資料移除,如資料為向量,可使用is.na()
來判斷資料是否為空值NA
,若為真TRUE
,則將資料移除。
## [1] FALSE FALSE TRUE FALSE FALSE
## [1] "a" "b" "d" "e"
若資料型態為資料框,可使用complete.cases
來選出完整的資料列,如果資料列是完整的,則會回傳真TRUE
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## [1] TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
## [13] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [25] FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
## [37] FALSE TRUE FALSE TRUE TRUE FALSE FALSE TRUE FALSE FALSE TRUE TRUE
## [49] TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [61] FALSE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
## [73] TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE
## [85] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
## [97] FALSE FALSE TRUE TRUE TRUE FALSE FALSE TRUE TRUE TRUE FALSE TRUE
## [109] TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE FALSE TRUE
## [121] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [133] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [145] TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 7 23 299 8.6 65 5 7
## 8 19 99 13.8 59 5 8
利用演算法補值也是一種解決辦法,可參考_skydome20_的R筆記–(10)遺漏值處理(Impute Missing Value)教學。
6.10 綜合練習範例Case study
在本範例中,介紹使用SportsAnalytics
(Eugster 2013) package 撈取NBA各球員的數據,並加以觀察分析。
6.10.1 載入資料
首先用library()
函數將SportsAnalytics
套件載入 (若尚未安裝此套件者,必須先安裝套件,可參考Chapter 1),並利用套件內提供的fetch_NBAPlayerStatistics()
函數,將對應年份之資料取出。
6.10.2 資料總覽
資料取出後,可用str()
函數總覽NBA1516
這個資料框的欄位與欄位類別
## 'data.frame': 476 obs. of 25 variables:
## $ League : Factor w/ 1 level "NBA": 1 1 1 1 1 1 1 1 1 1 ...
## $ Name : chr "Quincy Acy" "Jordan Adams" "Steven Adams" "Arron Afflalo" ...
## $ Team : Factor w/ 31 levels "ATL","BOS","BRO",..: 27 15 22 20 19 13 28 26 12 15 ...
## $ Position : Factor w/ 5 levels "C","PF","PG",..: 4 5 1 5 1 1 2 2 2 5 ...
## $ GamesPlayed : int 59 2 80 71 59 60 74 9 79 64 ...
## $ TotalMinutesPlayed : int 877 15 2019 2359 863 802 2260 37 1601 1622 ...
## $ FieldGoalsMade : int 119 2 261 354 150 134 536 5 191 215 ...
## $ FieldGoalsAttempted: int 214 6 426 799 314 225 1045 10 370 469 ...
## $ ThreesMade : int 19 0 0 91 0 0 0 0 0 15 ...
## $ ThreesAttempted : int 49 1 0 238 1 0 16 0 0 42 ...
## $ FreeThrowsMade : int 50 3 114 110 52 60 259 0 46 90 ...
## $ FreeThrowsAttempted: int 68 5 196 131 62 84 302 0 73 138 ...
## $ OffensiveRebounds : int 65 0 218 23 75 86 175 2 162 104 ...
## $ TotalRebounds : int 188 2 531 266 269 288 631 6 424 297 ...
## $ Assists : int 27 3 61 145 32 50 110 0 76 70 ...
## $ Steals : int 29 3 42 25 19 47 38 1 26 109 ...
## $ Turnovers : int 27 2 84 82 54 64 99 1 69 78 ...
## $ Blocks : int 24 0 89 10 36 68 81 2 42 18 ...
## $ PersonalFouls : int 103 2 223 142 134 139 151 1 147 175 ...
## $ Disqualifications : int 0 0 2 1 0 1 0 0 1 1 ...
## $ TotalPoints : int 307 7 636 909 352 328 1331 10 428 535 ...
## $ Technicals : int 3 0 2 1 2 0 0 0 0 1 ...
## $ Ejections : int 0 0 0 0 0 0 0 0 0 0 ...
## $ FlagrantFouls : int 0 0 0 0 0 0 0 0 0 0 ...
## $ GamesStarted : int 29 0 80 57 17 5 74 0 28 56 ...
可以發現此NBA1516
資料框內有476筆球員資料(觀察值, obs),每筆資料有25個欄位 (variables)。
6.10.3 資料預覽
如果想看資料框內容,可用head()
和tail()
快速瀏覽部分資料
## League Name Team Position GamesPlayed TotalMinutesPlayed
## 1 NBA Quincy Acy SAC SF 59 877
## 2 NBA Jordan Adams MEM SG 2 15
## 3 NBA Steven Adams OKL C 80 2019
## 4 NBA Arron Afflalo NYK SG 71 2359
## 5 NBA Alexis Ajinca NOR C 59 863
## 6 NBA Cole Aldrich LAC C 60 802
## FieldGoalsMade FieldGoalsAttempted ThreesMade ThreesAttempted FreeThrowsMade
## 1 119 214 19 49 50
## 2 2 6 0 1 3
## 3 261 426 0 0 114
## 4 354 799 91 238 110
## 5 150 314 0 1 52
## 6 134 225 0 0 60
## FreeThrowsAttempted OffensiveRebounds TotalRebounds Assists Steals Turnovers
## 1 68 65 188 27 29 27
## 2 5 0 2 3 3 2
## 3 196 218 531 61 42 84
## 4 131 23 266 145 25 82
## 5 62 75 269 32 19 54
## 6 84 86 288 50 47 64
## Blocks PersonalFouls Disqualifications TotalPoints Technicals Ejections
## 1 24 103 0 307 3 0
## 2 0 2 0 7 0 0
## 3 89 223 2 636 2 0
## 4 10 142 1 909 1 0
## 5 36 134 0 352 2 0
## 6 68 139 1 328 0 0
## FlagrantFouls GamesStarted
## 1 0 29
## 2 0 0
## 3 0 80
## 4 0 57
## 5 0 17
## 6 0 5
6.10.4 資料排序後篩選
觀察資料框的組成後,我們想要找出出場數最高的前五名選手的所有資料,此時可以利用order()
函數先由大到小排序(decreasing = T
)後,再用[,]
取子集。
NBA1516Order<-NBA1516[order(NBA1516$GamesPlayed,decreasing = T),]
NBA1516Order[1:5,] ##逗號前方放1~5,表示取1~5列;逗號後方空白,表示要取所有欄位
## League Name Team Position GamesPlayed TotalMinutesPlayed
## 11 NBA Al-farouq Aminu POR SF 82 2342
## 37 NBA Will Barton DEN SG 82 2355
## 48 NBA Bismack Biyombo TOR PF 82 1810
## 62 NBA Corey Brewer HOU SG 82 1670
## 118 NBA Gorgui Dieng MIN C 82 2222
## FieldGoalsMade FieldGoalsAttempted ThreesMade ThreesAttempted
## 11 299 719 126 349
## 37 426 984 112 324
## 48 156 288 0 1
## 62 212 552 61 225
## 118 308 578 6 20
## FreeThrowsMade FreeThrowsAttempted OffensiveRebounds TotalRebounds Assists
## 11 115 156 98 498 138
## 37 216 268 60 477 204
## 48 142 226 182 655 29
## 62 105 140 42 199 109
## 118 205 248 156 584 143
## Steals Turnovers Blocks PersonalFouls Disqualifications TotalPoints
## 11 72 120 53 171 0 839
## 37 71 139 39 147 0 1180
## 48 19 71 133 225 2 454
## 62 84 78 19 168 1 590
## 118 94 140 96 219 0 827
## Technicals Ejections FlagrantFouls GamesStarted
## 11 3 0 0 82
## 37 2 0 0 1
## 48 3 0 0 22
## 62 0 0 0 12
## 118 1 0 0 39
如果我們想要出出場分鐘數最高的前十名選手的名字,一樣可以用order()
函數先由大到小排序(decreasing = T
)後,再用[,]
取子集。
NBA1516OrderM<-NBA1516[order(NBA1516$TotalMinutesPlayed,decreasing = T),]
NBA1516OrderM[1:10,"Name"] ##逗號前方取1~10列;逗號後方放"Name",表示取名稱為Name之欄位
## [1] "James Harden" "Gordon Hayward" "Kemba Walker" "Trevor Ariza"
## [5] "Khris Middleton" "Kyle Lowry" "Marcus Morris" "Andrew Wiggins"
## [9] "Paul George" "Gi Antetokounmpo"
6.10.5 欄位值篩選
除了排序取值外,也可用欄位條件搜尋,舉例來說,可以取出所有波士頓賽爾迪克隊的選手資料,使用subset()
函數
## League Name Team Position GamesPlayed TotalMinutesPlayed
## 60 NBA Avery Bradley BOS PG 76 2536
## 89 NBA Coty Clarke BOS <NA> 4 8
## 102 NBA Jae Crowder BOS SF 73 2310
## 213 NBA R.j. Hunter BOS SG 36 319
## 228 NBA Jonas Jerebko BOS PF 78 1178
## 229 NBA Amir Johnson BOS PF 79 1798
## 300 NBA Jordan Mickey BOS PF 16 59
## 340 NBA Kelly Olynyk BOS C 69 1396
## 382 NBA Terry Rozier BOS PG 39 310
## 400 NBA Marcus Smart BOS PG 61 1666
## 416 NBA Jared Sullinger BOS PF 81 1917
## 422 NBA Isaiah Thomas BOS PG 82 2647
## 433 NBA Evan Turner BOS SG 81 2270
## 471 NBA James Young BOS SG 29 200
## 476 NBA Tyler Zeller BOS C 60 714
## FieldGoalsMade FieldGoalsAttempted ThreesMade ThreesAttempted
## 60 456 1018 147 406
## 89 2 4 2 2
## 102 359 812 122 363
## 213 36 98 19 63
## 228 118 286 43 108
## 229 250 427 10 43
## 300 8 22 0 0
## 340 253 556 85 210
## 382 29 106 6 27
## 400 184 529 61 241
## 416 351 807 29 104
## 422 591 1382 167 465
## 433 343 753 20 83
## 471 11 36 6 26
## 476 138 290 0 0
## FreeThrowsMade FreeThrowsAttempted OffensiveRebounds TotalRebounds Assists
## 60 96 123 48 220 158
## 89 0 0 0 1 0
## 102 196 239 70 373 135
## 213 6 7 2 37 13
## 228 61 78 77 288 62
## 229 69 121 178 505 137
## 300 5 10 6 13 1
## 340 96 128 72 281 105
## 382 8 10 24 63 37
## 400 129 166 76 255 186
## 416 103 161 194 673 187
## 422 474 544 46 243 509
## 433 148 179 50 397 359
## 471 1 4 4 26 9
## 476 88 108 62 178 29
## Steals Turnovers Blocks PersonalFouls Disqualifications TotalPoints
## 60 117 109 19 164 2 1155
## 89 0 1 0 0 0 6
## 102 126 83 35 198 4 1036
## 213 14 11 4 29 0 97
## 228 20 52 24 137 2 340
## 229 52 94 83 214 1 579
## 300 0 1 11 5 0 21
## 340 52 74 33 163 3 687
## 382 6 19 1 23 0 72
## 400 91 80 18 183 1 558
## 416 75 102 47 209 2 834
## 422 91 220 9 167 1 1823
## 433 80 169 28 139 0 854
## 471 6 5 1 17 0 29
## 476 10 46 22 97 1 364
## Technicals Ejections FlagrantFouls GamesStarted
## 60 0 0 0 72
## 89 0 0 0 0
## 102 3 0 0 73
## 213 0 0 0 0
## 228 1 0 0 0
## 229 0 0 0 76
## 300 0 0 0 0
## 340 1 0 0 8
## 382 0 0 0 0
## 400 2 0 0 10
## 416 2 0 0 73
## 422 9 0 0 79
## 433 2 0 0 12
## 471 0 0 0 0
## 476 0 0 0 3
6.10.6 字串條件搜尋後篩選
當然也可以結合字串搜尋函數grepl()
,將所有名字裡有“James”的選手資料取出
## League Name Team Position GamesPlayed TotalMinutesPlayed
## 15 NBA James Anderson SAC SG 51 721
## 132 NBA James Ennis NOR SF 22 329
## 178 NBA James Harden HOU SG 82 3121
## 222 NBA Lebron James CLE SF 76 2710
## 231 NBA James Johnson TOR PF 57 924
## 239 NBA James Jones CLE SG 48 466
## 286 NBA James Mcadoo GSW SG 41 265
## 471 NBA James Young BOS SG 29 200
## FieldGoalsMade FieldGoalsAttempted ThreesMade ThreesAttempted
## 15 67 178 23 86
## 132 54 113 26 58
## 178 710 1617 236 656
## 222 737 1416 87 282
## 231 114 240 20 66
## 239 59 143 41 104
## 286 45 84 1 2
## 471 11 36 6 26
## FreeThrowsMade FreeThrowsAttempted OffensiveRebounds TotalRebounds Assists
## 15 22 29 13 86 41
## 132 25 34 21 42 21
## 178 720 837 63 502 612
## 222 359 491 111 565 512
## 231 39 68 28 126 67
## 239 21 26 8 50 14
## 286 26 49 30 58 17
## 471 1 4 4 26 9
## Steals Turnovers Blocks PersonalFouls Disqualifications TotalPoints
## 15 21 42 14 54 0 179
## 132 16 19 5 28 1 159
## 178 138 374 51 229 1 2376
## 222 104 249 49 143 0 1920
## 231 29 54 33 84 0 287
## 239 11 13 10 50 0 180
## 286 10 16 8 39 0 117
## 471 6 5 1 17 0 29
## Technicals Ejections FlagrantFouls GamesStarted
## 15 0 0 0 15
## 132 0 0 0 5
## 178 2 0 0 82
## 222 3 0 0 76
## 231 0 0 0 32
## 239 1 0 0 0
## 286 0 0 0 1
## 471 0 0 0 0
References
Eugster, Manuel J. A. 2013. SportsAnalytics: Infrastructure for Sports Analytics. https://CRAN.R-project.org/package=SportsAnalytics.
Spinu, Vitalie, Garrett Grolemund, and Hadley Wickham. 2020. Lubridate: Make Dealing with Dates a Little Easier. https://CRAN.R-project.org/package=lubridate.
Wickham, Hadley. 2019b. Stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.
Wickham, Hadley. 2020. Reshape2: Flexibly Reshape Data: A Reboot of the Reshape Package. https://CRAN.R-project.org/package=reshape2.
Wickham, Hadley, and Lionel Henry. 2020. Tidyr: Tidy Messy Data. https://CRAN.R-project.org/package=tidyr.