前言
正如前文提到的,數據分析有一半以上的時間會花在對原始數據的整理及變換上,包括選取特定的分析變量、匯總并篩選滿足條件的數據、排序、加工處理原始變量并生成新的變量、以及分組匯總數據等等。這一點,我想大部分使用EXCEL的童鞋都深有體會,寫論文時,這么多的數據進行處理,手動匯總、篩選、變換,工作量實在是太大。而本文介紹的dplyr包簡直就是Hadley Wickham (ggplot2包的作者,被稱作“一個改變R的人”)大神為我們提供的“數據再加工”神器啊。
正文
本文試圖通過一個案例,對神奇的dplyr包的一些常用功能做簡要介紹。在此拋磚引玉,歡迎廣大盆友拍磚。先放上實踐課的一個問題:航行距離與到達延誤時間有什么關系???帶著這個問題,我們將首先使用dplyr包對給出的航班數據進行處理。
1.dplyr包的安裝加載與示例數據準備
1.1 安裝dplyr包
腳本輸入代碼:
install.packages("dplyr") #加載dplyr包
library(dplyr)
1.2安裝 nycflights13包,該軟件包中的飛機航班數據將用于本文中dplyr包相關函數的演示。
腳本輸入代碼:
install.packages("nyclights13") #加載nyclights13
library(nyclights13)
flights #查看數據表
dim(flights) #查看變量的維數
輸出結果如下:
如圖可知,nycflights13是一個data.frame類型的對象,包含336776條數據記錄、19個變量。
在處理數據之前,讓我們再來回顧一下數據處理的一般步驟:
選擇子集、列名重命名、刪除缺失數據、處理日期、數據類型轉換、數據排序
接下來,就可以進行數據處理了:
2.數據處理
2.1 選擇子集
所謂選擇子集,就是選擇出能夠實現分析目標的變量,本次數據分析的目標是得出航行距離與延誤時間的關系,因此,相應的子集就是以下幾個字段:
year 航班日期-年
month 航班日期-月
day 航班日期-月
dep_delay 起飛延遲時間(分)
arr_delay 到達延遲時間(分)
distance 航行里程(英里)
dest 目的地
為此,我們首先使用dpylr包里的select函數,進行變量篩選:
腳本輸入代碼:
myFlights <- select(flights, year,month, day,dep_delay,arr_delay,distance,dest) #篩選變量列
myFlights #查看數據表
如圖,子集選擇完畢。
2.2 列名重命名
為了讓列名簡單易懂,可以使用rename函數,進行列名重命名。
腳本輸入代碼:
myFlights <- rename(myFlights, destination = dest)
myFlights
重命名完畢。
2.3 刪除缺失數據
我們采用dplyr包中的filter()函數,進行缺失數據的刪除。腳本輸入代碼:
myFlights <- filter(myFlights,!is.na(dep_delay),!is.na(arr_delay))
myFlights
由圖可知,我們首先采用is.na()函數找出缺失值,再采用邏輯運算符“!X”將限定有效數據,最后用filter()函數“過濾”得到有效數據,成功地刪除了缺失數據(由原先的336,776個數據變為327,346個數據)。
2.4 數據排序
為了數據的整齊性,我們可以選擇相應的變量進行排序。這里要穿插一個排序函數arrange(),默認情況下,為升序排列,也可以對列名加desc()進行降序排序。腳本輸入代碼:
myFlights <- arrange(myFlights, desc(arr_delay))
myFlights
如圖所示,數據按照變量arr_delay(到達延遲時間(分))進行降序排列。
3.數據計算
數據處理之后,就進入計算分析步驟啦。在這個環節,主要歷經三個過程:
數據分組(Split):可以指定目標變量,將數據進行分組。由于本次分析的目標是找出航行距離與到達延誤時間的關系,所以我們得根據到達目的地對數據進行分組,從而計算出不同目的地的平行航行距離以及平均延誤時間;
應用函數(Apply):對不同組的數據,應用相應函數獲取所需統計指標。比如本次不同目的地的平行航行距離以及平均延誤時間;
組合結果(Combine):將計算后的統計指標值與第一步當中對應的分組進行組合。
3.1 數據分組
dplyr包里的分組是由group_by()函數實現的,腳本輸入代碼:
by_dest <- group_by(myFlights, destination)
class(by_dest)
by_dest
由圖可知,經分組后,一共有104組數據,即本次分析的目的地有104個。
3.2 應用函數及組合結果
我們使用dplyr包中的summarize()函數,進行數據統計指標的獲取及組合。計算出不同目的地的平行航行距離以及平均延誤時間。腳本輸入代碼:
delay_sum <- summarise(by_dest, count = n(),#統計各分組目的地的航班數
dist = mean(distance, na.rm = TRUE),
delay = mean(arr_delay, na.rm = TRUE))
delay_sum <- arrange(delay_sum, desc(count)) #按照航班數降序排列
delay_sum
從上圖可得知104個目的地的航班數排序。為了統計的科學合理性,需要對數據量太少的組別進行剔除,即剔除噪音數據,再次使用filter()函數剔除,剔除限度設為count>20。腳本輸入代碼:
delay_sum <- arrange(delay_sum, desc(count))
delay_sum <- filter(delay_sum , count > 20)
如上圖可知,剩余97組數據,即本次參與統計的目的地有97個。
PS.這里穿插一個好用的工具,“管道”,即通過使用操作符把數據集名作為開頭, 然后依次對此數據進行多步操作。這種運算符的編寫方式使得編程者可以按數據處理時的思路寫代碼, 一步一步操作不斷疊加,在程序上就可以非常清晰的體現數據處理的步驟與背后的邏輯。
通過管道的連接方式,讓數據或表達式的傳遞更高效,使用向右操作符%>%,可以直接把數據傳遞給下一個函數調用或表達式。(%>%是最常用的一個操作符,就是把左側準備的數據或表達式,傳遞給右側的函數調用或表達式進行運行,可以連續操作就像一個鏈條一樣。)拿上述的代碼進行舉例,在沒用管道之前,代碼是這樣的:
by_dest <- group_by(myFlights, destination)#按目的地分組
delay_sum <- summarise(by_dest, count = n(),#統計各分組目的地的航班數
dist = mean(distance, na.rm = TRUE),#計算平均航行距離
delay = mean(arr_delay, na.rm = TRUE))#計算平均延誤時間
delay_sum <- arrange(delay_sum, desc(count)) #按照航班數降序排列
delay_sum <- filter(delay_sum , count > 20)#剔除噪音數據
delay_sum#顯示列表
用了管道“%>%”,代碼是這樣的:
delay_sum <- myFlights %>% #將右側航行數據賦值給左側delay_sum
group_by(destination) %>% #對delay_sum進行分組
summarise( count = n(),
dist = mean(distance, na.rm = TRUE),
delay = mean(arr_delay, na.rm = TRUE)
) %>% #對分組后的delay_sum進行計算統計
filter(count > 20)#對統計結果進行噪音剔除
delay_sum#顯示列表
果然簡潔了很多!
4.數據顯示
所謂一圖勝千言啊,在大數據可視化普及的今天更是這樣。本次同樣使用Hadley Wickham 大神(ggplot2包的作者)貢獻的ggplot2包進行繪圖。調用ggplot()函數進行繪圖,腳本輸入代碼:
ggplot(data = delay_sum) +
geom_point(mapping = aes(x = dist, y = delay)) +#繪制平均航程(dist)和平均延誤時間(delay)的散點圖
geom_smooth(mapping = aes(x = dist, y = delay))#擬合一條平滑曲線(注意,連接符號+不可省略)
所得結果如下所示:
由上圖,我們就可以初步分析航程和延誤時間并非線性關系,至于這種非線性關系該怎么解釋,仍需進一步統計調查分析。