6 資料處理與清洗

6.1 Tidy Data

Each column is a variable. Each row is an observation.

  • 一個欄位(Column)內只有一個數值,最好要有凡人看得懂的Column Name
  • 不同的觀察值應該要在不同行(Raw)
  • 一張表裡面,有所有分析需要的資料
  • 如果一定要多張表,中間一定要有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(變數名稱)
num<-100
cha<-'200'
boo<-T
is.numeric(num)
## [1] TRUE
is.numeric(cha)
## [1] FALSE
is.character(num)
## [1] FALSE
is.character(cha)
## [1] TRUE
is.logical(boo)
## [1] TRUE

或使用class(變數名稱)函數,直接回傳資料型別

class(num)
## [1] "numeric"
class(cha)
## [1] "character"
class(boo)
## [1] "logical"
class(Sys.Date())
## [1] "Date"

6.2.2 資料型別轉換

使用以下as.函數轉換型別

  • 轉換為數字 as.numeric(變數名稱)
  • 轉換為文字 as.character(變數名稱)
  • 轉換為布林變數 as.logical(變數名稱)
as.numeric(cha)
## [1] 200
as.numeric(boo)
## [1] 1
as.character(num)
## [1] "100"
as.character(boo)
## [1] "TRUE"

若無法順利完成轉換,會回傳空值NA,並出現警告訊息Warning: NAs introduced by coercion,Warning: 強制變更過程中產生了 NA

as.numeric("abc")
## Warning: NAs introduced by coercion
## [1] NA

日期的轉換則建議使用lubridate(Grolemund, Spinu, and Wickham 2016) package,如果想要將年/月/日格式的文字轉換為日期物件,可使用ymd()函數(y表年year,m表月month,d表日day),如果想要將月/日/年格式的文字轉換為日期物件,則使用mdy()函數,以此類推。

library(lubridate)
ymd('2012/3/3')
## [1] "2012-03-03"
mdy('3/3/2012')
## [1] "2012-03-03"

6.3 文字字串處理

6.3.1 基本處理

  • 切割 strsplit()
  • 子集 substr()
  • 大小寫轉換 toupper() tolower()
  • 兩文字連接 paste() paste0()
  • 文字取代 gsub()
  • 前後空白去除 str_trim() 需安裝stringr(Wickham 2016d) package
strsplit ("Hello World"," ")
## [[1]]
## [1] "Hello" "World"
toupper("Hello World")
## [1] "HELLO WORLD"
tolower("Hello World")
## [1] "hello world"
paste("Hello", "World", sep='')
## [1] "HelloWorld"
substr("Hello World", start=2,stop=4)
## [1] "ell"
gsub("o","0","Hello World")
## [1] "Hell0 W0rld"
library(stringr)
str_trim(" Hello World ")
## [1] "Hello World"

6.3.2 搜尋字串

搜尋字串函數通常使用在比對文字向量,文字比對有分大小寫,依照回傳值的型態不同,有兩種常用函數,grep()grepl():

  • 回傳符合條件之向量位置(index) grep(搜尋條件,要搜尋的向量)
  • 回傳每個向量是否符合條件(TRUE or FALSE) grepl(搜尋條件,要搜尋的向量)
grep("A",c("Alex","Tom","Amy","Joy","Emma")) ##在姓名文字向量中尋找A,回傳包含"A"之元素位置
## [1] 1 3
grepl("A",c("Alex","Tom","Amy","Joy","Emma")) ##在姓名文字向量中尋找A,回傳各元素是否包含"A"
## [1]  TRUE FALSE  TRUE FALSE FALSE
grepl("a",c("Alex","Tom","Amy","Joy","Emma")) ##在姓名文字向量中尋找a,回傳各元素是否包含"a"
## [1] FALSE FALSE FALSE FALSE  TRUE

6.4 子集Subset

6.4.1 一維資料 (向量)

在向量章節{#vector}有介紹使用[]取出單一或多個元素的方法

letters ##R語言內建資料之一
##  [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"
letters[1] ##取出letters向量的第一個元素
## [1] "a"
letters[1:10] ##取出letters向量的前十個元素
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
letters[c(1,3,5)] ##取出letters向量的第1,3,5個元素
## [1] "a" "c" "e"
letters[c(-1,-3,-5)] ##取出letters向量除了第1,3,5個元素之外的所有元素
##  [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()函數

head(letters,5) ##取出letters向量的前五個元素
## [1] "a" "b" "c" "d" "e"
tail(letters,3) ##取出letters向量的後三個元素
## [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]
data(iris)
iris[1,2] ##第一列Row,第二行Column
## [1] 3.5
iris[1:3,] ##第1~3列Row,所有的行Column
##   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
iris[,"Species"] ##所有的列Row,名稱為Species的行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
iris[1:10,c(T,F,T,F,T)] ##第1~10列Row,第1,3,5行Column (TRUE)
##    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的篩選

iris$Species ##所有的列Row,名稱為Species的行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(資料表,篩選邏輯)

subset(iris,Species=="virginica") ##Species等於"virginica"的列Row,所有的行Column
##     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()

knitr::kable(iris[grepl("color",iris$Species),]) ##Species包含"color"的列,所有的行
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

若想要快速取得資料框的前幾列(Raw)或後幾列,也可使用head()tail()函數

head(iris,5) ##取出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
tail(iris,3) ##取出iris資料框的後三列
##     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()函數可直接對向量做由小到大的排序

head(islands) ##排序前的前六筆資料
##       Africa   Antarctica         Asia    Australia Axel Heiberg       Baffin 
##        11506         5500        16988         2968           16          184
head(sort(islands)) ##由小到大排序後的前六筆資料
##       Vancouver          Hainan Prince of Wales           Timor          Kyushu 
##              12              13              13              13              14 
##          Taiwan 
##              14

如需由大到小排序,可將decreasing參數設為TRUE

head(sort(islands,decreasing = T)) ##由大到小排序後的前六筆資料
##          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個元素。

order(iris$Sepal.Length)
##   [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
iris$Sepal.Length[14]
## [1] 4.3

若將decreasing參數設定為TRUE,則會回傳由大到小的元素位置,以iris$Sepal.Length為例,回傳的第一個位置為132,表示iris$Sepal.Length中,數值最大的元素為第132個元素。

order(iris$Sepal.Length,decreasing = T)
##   [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
iris$Sepal.Length[132]
## [1] 7.9

依照order回傳的元素位置,重新排序iris資料框

head(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
head(iris[order(iris$Sepal.Length),]) ##依照Sepal.Length欄位數值大小排序後的前六筆資料
##    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
head(iris[order(iris$Sepal.Length,decreasing = T),]) ##改為由大到小排序的前六筆資料
##     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()的參數可以是向量,也可以是資料框,使用向量做資料整合範例:

rbind(c(1,2,3), #第一列
      c(4,5,6)  #第二列
      ) 
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6

使用資料框與向量做資料整合範例:

irisAdd<-rbind(iris, #資料框
      c(1,1,1,1,"versicolor")  #新增一列
      ) 
tail(irisAdd)
##     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

使用向量做資料整合範例:

cbind(c(1,2,3), #第一行
      c(4,5,6)  #第二行
      ) 
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6

使用資料框與向量做資料整合範例:

irisAdd<-cbind(iris, #資料框
      rep("Add",nrow(iris))  #新增一行
      ) 
tail(irisAdd)
##     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 長表與寬表

在資料處理的過程中,常因各種需求,需要執行長寬表互換的動作,在R中有很好用的套件reshape2(Wickham 2016b) package,提供完整的轉換功能,最常使用的是

  • 寬表轉長表 melt(資料框/寬表,id.vars=需要保留的欄位)
  • 長表轉寬表 dcast(資料框/長表,寬表分列依據~分欄位依據)

原來的airquality資料框中,有Ozone, Solar.R, Wind, Temp, Month, Day等六個欄位 (Column),屬於寬表,以下範例將保留Month和Day兩個欄位,並將其他欄位的名稱整合至variable欄位,數值整合至value欄位,寬表轉長表範例如下:

library(reshape2)
head(airquality)
##   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
airqualityM<-melt(airquality,id.vars = c("Month","Day")) ##欄位需要保留"Month","Day"
head(airqualityM)
##   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

6.8 遺漏值處理

遺漏值(Missing Value)常常出現在真實資料內,在數值運算時常會有問題,最簡單的方法是將有缺值的資料移除,如資料為向量,可使用is.na()來判斷資料是否為空值NA,若為真TRUE,則將資料移除。

naVec<-c("a","b",NA,"d","e")
is.na(naVec)
## [1] FALSE FALSE  TRUE FALSE FALSE
naVec[!is.na(naVec)] ##保留所有在is.na()檢查回傳FALSE的元素
## [1] "a" "b" "d" "e"

若資料型態為資料框,可使用complete.cases來選出完整的資料列,如果資料列是完整的,則會回傳真TRUE

head(airquality)
##   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
complete.cases(airquality) 
##   [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
head(airquality[complete.cases(airquality),]) ##保留所有在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
## 7    23     299  8.6   65     5   7
## 8    19      99 13.8   59     5   8

利用演算法補值也是一種解決辦法,可參考_skydome20_的R筆記–(10)遺漏值處理(Impute Missing Value)教學。

6.9 綜合練習範例Case study

在本範例中,介紹使用SportsAnalytics (Eugster 2013) package 撈取NBA各球員的數據,並加以觀察分析。

6.9.1 載入資料

首先用library()函數將SportsAnalytics套件載入 (若尚未安裝此套件者,必須先安裝套件,可參考Chapter 1),並利用套件內提供的fetch_NBAPlayerStatistics()函數,將對應年份之資料取出。

library(SportsAnalytics)
NBA1516<-fetch_NBAPlayerStatistics("15-16")

6.9.2 資料總覽

資料取出後,可用str()函數總覽NBA1516這個資料框的欄位與欄位類別

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)。 ###資料預覽 如果想看資料框內容,可用head()tail()快速瀏覽部分資料

head(NBA1516)
##   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.9.3 資料排序後篩選

觀察資料框的組成後,我們想要找出出場數的前五名選手的所有資料,此時可以利用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.9.4 欄位值篩選

除了排序取值外,也可用欄位條件搜尋,舉例來說,可以取出所有波士頓賽爾迪克隊的選手資料,使用subset()函數

subset(NBA1516,Team=="BOS")
##     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.9.5 字串條件搜尋後篩選

當然也可以結合字串搜尋函數grepl(),將所有名字裡有“James”的選手資料取出

NBA1516[grepl("James",NBA1516$Name),]
##     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

Grolemund, Garrett, Vitalie Spinu, and Hadley Wickham. 2016. Lubridate: Make Dealing with Dates a Little Easier. https://CRAN.R-project.org/package=lubridate.

Wickham, Hadley. 2016d. Stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.

Wickham, Hadley. 2016b. Reshape2: Flexibly Reshape Data: A Reboot of the Reshape Package. https://CRAN.R-project.org/package=reshape2.

Eugster, Manuel J. A. 2013. SportsAnalytics: Infrastructure for Sports Analytics. https://CRAN.R-project.org/package=SportsAnalytics.