R學習筆記 第六篇:資料變換和清理
用R的分組操作之前,首先要了解R語言包,包實質上是實現特定功能的,預先寫好的程式碼庫(library),R擁有大量的軟體包,許多包都是由某一領域的專家編寫的,但並不是所有的包都有很高的質量的,在使用包之前,最好導社群中瞭解其他網友的反饋。
安裝包,引用包和解除安裝包的命令分別是:
install.packages("package-name") library(package-name)
remove.packages("package-name")
資料分析的工作,80%的時間耗費在處理資料上,而資料處理的過程可以分為:分離-操作-結合(Split-Apply-Combine),也就是說,先將資料根據特定的欄位分組,每個分組都是獨立的;然後,對每個分組執行轉換,最後把轉換後的結果組合在一起,在資料處理中,經常需要迴圈訪問資料,R語言是向量化的,天生具有處理迴圈操作的優勢。
一,分組聚合
在apply函式家族中,apply函式只能用於矩陣,lapply函式能夠用於向量和列表(list),其工作原理是把一個函式應用於一個列表中的每個元素上,並且把結果作為列表返回;sapply處理列表,返回向量。mapply函式,把呼叫的函式應用到多個列表的每一個元素中。
tapply函式用於分組聚合運算,在研究資料時,有時需要對資料按照特定的欄位進行分組,然後統計各個分組的資料,這就是SQL語法中的分組聚合。在R語言中,可以通過三步實現:拆分-應用-合併(Split-Apply-Combine)
例如,對玩家的遊戲成績進行統計和分析,建立示例資料:
> players_scores=data.frame( + player=rep(c('Tom','Dick','Jim'),times=c(2,5,3)), + score=round(runif(10,1,100),-1) + )
計算每個玩家的平均得分,首先對玩家分組,split函式的作用是按照特定的欄位對資料框進行分組,第一個引數是資料框物件,第二個引數是分組欄位,split函式返回的結果是列表物件。
例如,split(score,player)函式的作用是按照player欄位把資料框中的score拆分成一組,也就是說,player 相同的score是同一個分組,填充到同一個列表項中:
> (scores_by_player=with(players_scores,split(score,player))) $Dick [1] 70 20 30 70 70 $Jim [1] 80 90 50 $Tom [1] 8090
第二步是對每個分組計算平均分,利用lapply函式,把函式引用於列表的每個列表項中:
list_mean_by_player=lapply(scores_by_player,mean)
第三步是把結果合併到單個向量中,也就是把列表轉換成向量,
> unlist(list_mean_by_player) Dick Jim Tom 52.00000 73.33333 85.00000
在資料分析中,”拆分-應用-合併“ 顯示十分繁瑣,tapply函式一次完成所有的三個步驟,一氣呵成:
with(players_scores,tapply(score,player,mean))
tapply函式常用的引數共有三個,第一個引數是:資料框物件或向量,第二個引數是因子列表,也就是分組欄位,第三個引數是指對單個分組應用的函式變數:
tapply(X, INDEX, FUN = NULL, ...)
by函式和aggregate函式是tapply函式的包裝函式,功能相同,介面稍微不同。
二,aggregate函式
aggregate函式把資料分離為單獨的子集,為每一個子集計算聚合值,然後把聚合值結合(combine)在一起返回。aggregate函式第一個引數是:price~cut,這是formula物件,包括符號“ ~”,以及在符號“~”兩側的變數,左側代表要計算聚合值的變數(聚合變數),右側代表分組的變數,函式依據分組變數,把資料分離為多個單獨的子集。第二個引數是操作的資料框,第三個引數是應用在符號“~”左側的函式,例如:
> library(ggplot2) > data("diamonds")
data函式的作用是載入指定的資料集,本例將載入ggplot2包中的diamonds資料集,這個資料集在下文直接引用。
使用aggregate函式操作diamonds資料集,按照cut欄位分組,函式mean的作用是為每個分組計算prince的平均值:
> aggregate(price~cut,diamonds,mean)
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 ....
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
還可以在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 ....
三,plyr包
plyr包基本上可以取代apply函式家族,plyr包核心函式的特點是:**ply,所有的函式名都由5個字元組成,且最後三個字元是ply,函式名的第一個字元代表輸入值的型別,第二個字元代表輸出值的型別。型別簡寫是:
- d:data.frame
- l:list
- a:array,vector,matrix
- r:代表replicate
- _:捨棄輸出結果
plyr包的核心函式,使用起來十分方便,使用之前,需要載入和引用plyr包:
install.packages("plyr") library(plyr)
1,ddply函式
plyr包中最常用的函式是ddply函式,函式的第一個引數是要操作的資料框,第二個引數是:要進行拆分的列的名稱,第三個引數是要應用到每個元素上的函式。傳遞列時,無需引號,但是需要包含在.(col_name)的呼叫之後。
使用colwise函式,使ddply函式把第三個引數引用於每一列,除了第二個引數指定的資料列之外,或者使用summarize函式對指定的列執行操作:
> ddply(diamonds,.(color),summarize,avg_price=mean(price),avg_carat=mean(carat)) color avg_price avg_carat 1 D 3169.954 0.6577948 2 E 3076.752 0.6578667
.....
2,each函式
each函式,能夠使函式aggregate函式同時呼叫多個函式
> aggregate(cbind(price,carat)~cut+color,diamonds,each(mean,sum)) cut color price.mean price.sum carat.mean carat.sum 1 Fair D 4291.061 699443.000 0.9201227 149.9800000 2 Good D 3405.382 2254363.000 0.7445166 492.8700000 ......
三,dplyr包
dplyr
包只能用於tibble型別的物件,用於對資料進行資料清理和轉換,使用以下命令載入和引用dplyr包:
install.packages("dplyr") library(dplyr)
tibble 型別是dplyr包特有的物件型別(data frame tbl / tbl_df)。在利用dplyr
包處理資料之前,首先需要把資料框裝載成tibble型別,可以呼叫 tbl_df
函式把資料框型別的資料裝載成 tibble 型別的資料物件:
> df=tbl_df(diamonds)
1,投影函式(select)
從tibble變數中,選擇特定的資料列顯示,select函式的第一個引數是tibble變數:
> select(df,carat,cut,color)
2,篩選函式(filter)
從tibble變數中,按照特定的條件過濾資料:
> filter(df,color=='E')
3,轉換函式(mutate)
根據tibble變數中的資料,應用指定的公式,派生新的資料列,或重寫已經存在的資料列:
> mutate(df,avg_ct=price/carat)
4,彙總函式(summarize)
對tibble變數執行聚合運算,如果tibble已經被分組,那麼單獨對每個分組進行聚合運算:
> summarize(df,avg_prince=mean(price),avg_ct=mean(carat))
5,分組函式(group_by)和移除分組(ungroup)
被分組之後,tibble變數處於分組狀態,可以使用ungroup函式,移除tibble變數的分組狀態。
group_by(df,color)
6,管道操作符(%>%)
管道操作符(%>%)用於把前一步操作的結果集(變數型別是tibble)傳遞到下一個函式中,賦值給函式的第一個引數中:
> group_by(df,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
7,排序函式(arrange)
arrange對tibble變數進行排序,預設是按照欄位的升序值排序,使用desc(field),可以按照欄位的降序值排序:
> group_by(df,color) %>% summarize(avg_price=mean(price)) %>% arrange(desc(avg_price))