數據分析的工作,80%的時間耗費在處理數據上,而數據處理的主要過程可以分為:分離-操作-結合(Split-Apply-Combine),也就是說,首先,把數據根據特定的字段分組,每個分組都是獨立的;然后,對每個分組按照業務需求執行轉換;最后,把轉換后的結果組合在一起。在數據處理中,經常需要循環訪問數據,R語言是矢量化的,天生具有處理循環操作的優勢。
使用ggplot2包中的diamonds數據集做為示例數據
> install.packages('ggplot2')
> library(ggplot2) > data("diamonds")
data()函數的作用是加載指定的數據集,本例將加載ggplot2包中的diamonds數據集,這個數據集在下文直接引用。
一,使用aggregate()函數做數據變換
在研究數據時,有時需要對數據按照特定的字段進行分組,然后統計各個分組的數據,這就是SQL語法中的分組-聚合操作,使用aggregate()函數對數據進行簡單的數據處理。
aggregate()函數用於把數據分離為單獨的子集,為每一個子集計算聚合值,然后把聚合值結合(combine)在一起返回。
aggregate(formula, data, FUN, ...,subset, na.action = na.omit)
參數注釋:
- formula:指定formula對象,包括符號“ ~”,以及在符號“~”兩側的變量,左側代表要計算聚合值的變量(聚合變量),右側代表分組的變量,例如,price~cut,函數依據分組變量,把數據分離為多個單獨的子集。
- data:指定操作的數據框;
- FUN:該參數用於指定函數,該函數應用在符號“~”左側的變量;
- ...:指定傳遞給FUN函數的其他參數;
- subset:向量類型,可選參數,用於指定data的觀測子集;
- na.action: 如何處理缺失值,默認為忽略NA。如果不選擇na.omit,則需指定函數去處理NA。
1,單個分組變量
使用aggregate() 函數操作diamonds數據集,按照cut字段分組,函數mean的作用是為每個分組計算prince的平均值:
aggregate(price~cut,diamonds,mean)
2,多個分組變量
aggregate()函數能夠添加多個分組變量,只需要在formula右側添加變量,並用加號“+”隔離:
> aggregate(price~cut+color,diamonds,mean) cut color price 1 Fair D 4291.061 2 Good D 3405.382 3 Very Good D 3470.467 ....
3,多個聚合變量
aggregate()函數能夠添加多個聚合變量,只需要在formula左側,使用函數cbind()把兩個變量組合起來:
> aggregate(cbind(price,carat)~cut,diamonds,mean) cut price carat 1 Fair 4358.758 1.0461366 2 Good 3928.864 0.8491847 3 Very Good 3981.760 0.8063814 4 Premium 4584.258 0.8919549 5 Ideal 3457.542 0.7028370
4,多個分組變量和多個聚合變量
aggregate()函數能夠formular對象的兩側分別添加多個變量,按照多個分組變量和多個聚合變量執行聚合運算
> aggregate(cbind(price,carat)~cut+color,diamonds,mean) cut color price carat 1 Fair D 4291.061 0.9201227 2 Good D 3405.382 0.7445166 ....
二,計數
R中計數比較特殊,plyr包中有一個計算函數count(),參數vars定義分組的變量,該函數會把重復值計算N次:
count(df, vars = NULL)
使用aggregate()來實現分組計數,使用length(x)來計算向量中元素的個數,該函數會把重復值計算N次:
aggregate(cut~color,diamonds,length)
為了計算唯一值的數量,可以使用unique(x),在計數之前,對向量元素去重:
aggregate(cut~color,diamonds,function(x) length(unique(x)))
三,數據變換(dplyr包)
dplyr包提供靈活的數據操作,用於對數據框執行轉化和重塑,這個包是plyr包的升級版本,側重於處理數據框對象,因此其名字帶d(data frame),dplyr包是R開發人員必學必會的包。
dplyr包有三個主要的目標:
- 更加靈活和簡單地處理數據框;
- 使用內存,提高數據處理的性能;
- 使用相同的接口處理數據,無論數據存儲在何處,無論是在數據框中,數據表或數據庫。
install.packages("dplyr") library(dplyr)
dplyr
包只能用於tibble(簡稱tbl)類型的對象,tibble 類型是dplyr包特有的對象類型(data frame tbl / tbl_df)。在利用dplyr
包處理數據之前,建議把數據框裝載成tibble類型,可以調用 tbl_df()
函數把數據框類型轉化成 tibble 類型的數據對象:
> df <- tbl_df(diamonds)
2,投影函數(select)
從tbl對象中,選擇特定的數據列顯示,select()函數的第一個參數是tibble對象,后續的參數是tbl對象中的變量名:
> select(df,carat,cut,color)
2,篩選函數(filter)
從tbl對象中,按照特定的條件過濾數據:
> filter(df,color=='E')
3,轉換函數(mutate)
根據tbl對象中的數據,應用指定的公式,派生新的數據列,或重寫已經存在的數據列:
> mutate(df,avg_ct=price/carat)
4,匯總函數(summarize)
對tbl對象執行聚合運算,如果tbl對象已經被分組,那么單獨對每個分組進行聚合運算:
> summarize(df,avg_prince=mean(price),avg_ct=mean(carat))
5,分組函數(group_by)和移除分組(ungroup)
使用group_by()函數對tbl對象執行分組,被分組之后,tbl對象處於分組狀態,可以使用ungroup函數,移除tbl對象的分組狀態。
group_by(df,color)
6,排序函數(arrange)
arrange()函數對tbl變量進行排序,默認是按照字段的升序值排序,使用desc(field),可以按照字段的降序值排序:
> arrange(df,color)
7,管道操作符(%>%)
管道操作符(%>%)用於把前一步操作的結果集(變量類型是tbl)傳遞到給函數的第一個參數中,同時函數的第一個參數可以省略,例如:
> df %>% group_by(color) %>% summarize(mean(price)) # A tibble: 7 x 2 color `mean(price)` <ord> <dbl> 1 D 3169.954 2 E 3076.752 3 F 3724.886 4 G 3999.136 5 H 4486.669 6 I 5091.875 7 J 5323.818
8,連接操作(join)
dplyr包還提供了連接(join)操作,
inner_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...) left_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...) right_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...) full_join(x, y, by = NULL, copy = FALSE, suffix = c(".x", ".y"), ...) semi_join(x, y, by = NULL, copy = FALSE, ...) anti_join(x, y, by = NULL, copy = FALSE, ...)
參數注釋:
- by:設置兩個數據集用於匹配的字段名,默認使用全部的同名字段進行匹配,如果兩個數據集需要匹配的字段名不同,可以直接用等號指定匹配的字段名,例如, by = c("a" = "b"),表示用x.a和y.b進行匹配。
- copy:如果兩個數據集來自不同的數據源,copy設置為TRUE時,會把數據集y的數據復制到數據集x中,出於性能上的考慮,需要謹慎設置copy參數為TRUE。
- suffix:合並后的數據集中同名變量,會自動添加suffix中設置的后綴加以區分。
9,集合操作(set)
#取兩個集合的交集
intersect(x,y, ...)
#取兩個集合的並集,並進行去重
union(x,y, ...)
#取兩個集合的並集,不去重
union_all(x,y, ...)
#取兩個集合的差集
setdiff(x,y, ...)
#判斷兩個集合是否相等
setequal(x, y, ...)
10,綁定操作
dplyr包提供了按行/列合並數據集的函數,合並的對象為數據框,也可以是能夠轉換為數據框的列表。按行合並函數bind_rows()通過列名進行匹配,不匹配的值使用NA替代,類似於base:: rbind()函數。按列合並函數bind_cols()通過行號匹配,因此合並的數據框必須有相同的行數,函數類似於base:: cbind()函數。原數據集行名稱會被過濾掉。
#按行合並,.id添加新列用於指明合並后每條數據來自的源數據框 bind_rows(...,.id = NULL) #按列合並 bind_cols(...) #合並數據集 combine(...)
11,排名操作
row_number(x)
ntile(x, n)
min_rank(x)
dense_rank(x)
percent_rank(x)
cume_dist(x)
例如,對一個向量的元素進行排序:
x <- c(5, 1, 3, 2, 2, NA) row_number(x)
12,去重
對數據對象去重
distinct(data, ..., keep_all = FALSE)
參數注釋:
- data:tbl對象
- ... :可選的變量,用於指定去重的變量,如果去重的變量不唯一,那么只保留第一個觀測
- keep_all:設置為TRUE時,所有的變量都保留到.data,如果...的組合不唯一,那么只保留第一行的觀測的各個變量值
13,計數
計數使用函數 n() 來實現,而統計數據集中無重復值的數量使用函數 n_distinct()來實現:
n()
n_distinct(..., na.rm = FALSE)
統計各個分組的觀測數量,只能用於 summarise(), mutate() 和 filter() 中
carriers <- group_by(flights, carrier) summarise(carriers, n()) mutate(carriers, n = n()) filter(carriers, n() < 100)
參考文檔: