【轉載】R語言資料處理——資料合併與追加
資料結構的塑造是資料視覺化前重要的一環,雖說本公眾號重心在於資料視覺化,可是涉及到一些至關重要的資料整合技巧,還是有必要跟大家分享一下的。
在視覺化前的資料處理技巧中,匯入匯出、長寬轉換已經跟大家詳細的介紹過了。
今天跟**家分享資料集的合併與追加,並且這裡根據所依賴函式的處理效率,給出諾幹套解決方案。
資料合併操作涉及以下幾個問題:
橫向合併;
1. 是否需要匹配欄位
1.1 匹配欄位合併
1.1.1 主欄位同名
1.1.2 主欄位不同名
1.2 無需匹配欄位合併
縱向合併:(情況比較簡單,列欄位數量相同,名稱相同)
因為縱向合併情況比較簡單,所以本篇講解也著重以橫向合併為主,按照以上幾個問題,需要用到的函式列舉如下:
cbind rbind merge plyr::join tidyr:: inner_join/full_join/left_join/right_join
首先介紹base內建的兩三個函式:
cbind rbind merge
###橫向追加(無需匹配欄位)
資料集構造如下:
ID<-c(1,2,3,4)
Name<-c("A","B","C","D")
Score<-c(60,70,80,90)
Sex<-c("M","F","M","M")
One<-data.frame(ID,Name)
Two<-data.frame(Score,Sex)
合併:
Total<-cbind(One,Two)
可以看到cbind函式橫向合併無需匹配主欄位,僅僅是將兩個資料集橫向拼接在一起。
###縱向合併
構造資料集:
ID<-c(1,2,3,4)
Name<-c("A","B","C","D")
Student1<-data.frame(ID,Name)
ID<-c(5,6,7,8)
Name<-c("E","F","G","H")
Student2<-data.frame(ID,Name)
合併:
Total_student3<-rbind(Student1,Student2)
以上通過rbind函式對Student1,Student2兩個資料集進行縱向合併(也稱追加)。
merge函式:
merge函式主要針對橫向(列欄位)合併,而且可以針對主欄位(主鍵)進行匹配,如果主欄位名稱不同,還可以指定前後相匹配的主欄位。
基本語法如下:
merge(x, y, by = , by.x = , by.y = , all = , all.x = , all.y = , sort = , suffixes = , incomparables = , ...)
具體引數解釋如下:
接下來按照名相同與不同分兩種情況介紹;
列名相同:
ID<-c(1,2,3,4)
name<-c("A","B","C","D")
score<-c(60,70,80,90)
student1<-data.frame(ID,name)
student2<-data.frame(ID,score)
total_student1<-merge(student1,student2,by="ID")
#以上兩個資料集有相同的列名(ID)時,by引數可以省略(by="ID")
以上兩個資料集中,authors和books中有相同屬性的主欄位(surname&name)但是主欄位名稱不同,這裡需要給merge函式指定匹配的主欄位。
橫向合併的四種類型:
#inner(內部連結)只合並交集
m1 <- merge(authors, books, by.x = "surname", by.y = "name")
#left join(左連線)
m2 <- merge(authors, books, by.x = "surname", by.y = "name",all.x=TRUE)
#right join(右連線)
m3 <- merge(authors, books, by.x = "surname", by.y = "name",all.y=TRUE)
#all_join(外連線)
m4 <- merge(authors, books, by.x = "surname", by.y = "name",all=TRUE)
plyr::join函式
join函式源於plyr包(該包作者就是大名鼎鼎的Hadley Wickham,就是ggplot2的開發者,當然它開發的包還有很多),使用前需要載入:
以下是該函式語法:
join(x, y, by = NULL, type = "left", match = "all")
當兩個資料集主欄位有相同名稱時,by引數可以省略(by="name"),當名稱不同時,需指定左右兩個資料集匹配的主欄位名稱。
join(x,y,by=intersect("Name","name"),type = "left")
以下我只演示相同主欄位名稱下的四種類型合併語句:
構造待合併資料集:
x<-data.frame(name=c("John","Paul","George","Ringo","Stuart","Pete"),instrument=c("guitar","bass","guitar","drums","bass","drums"))
y<-data.frame(name=c("John","Paul","George","Ringo","Brian"),band=c("TRUE","TRUE","TRUE","TRUE","FALSE"))
#left_join
data1<-join(x,y,by="name",type = "left")
#right_join
data2<-join(x,y,by="name",type = "right")
#inner_join
data3<-join(x,y,by="name",type = "inner")
#full_join
data4<-join(x,y,by="name",type = "full")
合併函式與merge函式基本相同。
dplyr::inner_join/full_join/left_join/right_join
(告訴你一個不幸的訊息,該包作者還是Hadley Wickham,沒辦法,一個贏者通吃的時代,誰讓人家有才任性呢哈哈~_~)
dplyr的資料合併語句要比plyr還要精練:
x<-data.frame(Name=c("John","Paul","George","Ringo","Stuart","Pete"),instrument=c("guitar","bass","guitar","drums","bass","drums"))
y<-data.frame(name=c("John","Paul","George","Ringo","Brian"),band=c("TRUE","TRUE","TRUE","TRUE","FALSE"))
#(1)inner_join(x, y) :只包含同時出現在x,y表中的行
data1<-inner_join(x,y,by=c("Name"="name"))
#(2)left_join(x, y) :包含所有x中以及y中匹配的行
data2<-left_join(x,y,by=c("Name"="name"))
#(3)right_join(x, y,by=c("Name"="name")) :包含所有y中以及x中匹配的行
data3<-right_join(x,y,by=c("Name"="name"))
#(4)full_join(x,y,by=c("Name"="name")) :包含所以x、y中的行
data4<-full_join(x,y,by=c("Name"="name"))
#(5)semi_join(x, y) :包含x中,在y中有匹配的行,結果為x的子集
data5<-semi_join(x,y,by=c("Name"="name"))
#(6)anti_join(x, y) :包含x中,不匹配y的行,結果為x的子集,與semi_join相反
data6<-anti_join(x,y)
以上連線型別中,前四個(內連線、外連線、左連線、右連線)最為常用,大家可以將dplyr和plyr以及merge函式三種連線方式進行對比記憶。
下面聊一列為啥要專門講一節資料連線方式:
因為……
在excel中……
這種資料連線真的……真的……真的……太費勁了
我所知道的連線方式——
第一:手動複製黏貼;(大家不要隨便作死)
第二:最古老的Microsoft Query(藏在excel資料匯入選單的最底層,據說微軟也不更新了,如果的excel是精簡版的,可能都沒法呼叫,選單特醜)
第三:資料透視表;Alt+D+P(為啥微軟要把呼叫資料透視表多表合併的選單隱藏起來只能用快捷鍵,太煩人了)
第四:微軟的最新商務智慧應用——PowerBI(其中的PowerQuery、PowerPivot)
第五:第三方的效率外掛(很多VBA大神寫過這些辦公外掛,但是我就不愛用,多裝一個,Excel啟動拖後兩秒鐘,時間就是金錢啊你說是不)
以上四種方式(第一種除外),雖說都可以完成資料合併操作,但是效率上不敢恭維,每次都得走一遍選單流程。如果有點R語言基礎的同學,強烈建議將這些操作放在R中操作,資料匯入匯出、長寬轉換、橫縱合併,只需修改一下程式碼路徑、引數分分鐘搞定。
當然對於有資料庫基礎的同學(相信大部分同學都有吧,應該是大學本科的必修課)來講,寫幾個SQL也可以瞬間完成。
雖然已經N多年沒有用過了,但是還是想在這裡獻醜一下:
內連線 inner join
語法:select * from x inner join y on x.Name =y.name
左連線 left join(左表中所有資料,右表中對應資料)
語法:select * from x left join y on x.Name = y.name
右連線 right join(右表中所有資料,左表中對應資料)
語法:select * from x right join y on x.Name = y.name
全連線 full join
語法:select * from x full join y on x.Name = y.name
我是一個比較懶、嫌麻煩但注重效率的人,很多關於資料處理上的需求,如果能用簡單的方式解決(比如VBA、R或者效率函式),我都不會去選擇安裝外掛或者外部軟體,一方面太浪費時間,操作麻煩;另一方面,使用外掛大多需要用選單點選,以後遇到同樣的需要還得從新走一遍流程,所以我更傾向用簡單的可重複利用的程式碼來解決。
簡單、省事兒、快捷、可重複……