dplyr
和data.table
是R的两个高效数据处理包,这两个包有它们各自的优点。dplyr
包的语法更加优雅,提供了更易于人类所能理解的自然语言。data.table
包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table
在某些情况下执行效率更高(见这里)。在性能和内存受约束的情况,data.table
包或许是首选的R包。关于dplyr
和data.table
包之间的对比可以参考StackOverflow和Quora。
data.table
和dplyr
包的参考手册分别见手册1和手册2。有关dplyr
包的更多介绍可以参考DataScience+的文章以及雪晴数据网免费视频教程
背景介绍
在我的数据处理任务中,我算是使用dplyr
和data.table
包很长一段时间的用户了。对于了解这两个包其中之一的读者来说,我会使用这两个包来完成一个相同的任务,以便帮助大家快速的学习另一个R包。如果你了解其中之一,并对学习另一个R包感兴趣,那么这篇文章就是为你准备的。
dplyr
dplyr
包的5个函数可以有效的执行数据处理的大部分任务,分别如下:
select:用于选取一列或者多列
filter:用于选取特定条件下的某些行
arrange:用于实现数据一列或多列的升降排序
mutate:用于在数据集中添加列
summarise:用于实现数据汇总
data.table
data.table
包提供了一个非常简洁的通用格式:DT[i,j,by]
,可以理解为:对于数据集DT,选取子集行i,通过by分组计算j。
数据处理
首先,我们需要加载一些R包:
library(dplyr) library(data.table) library(lubridate) library(jsonlite) library(tidyr) library(ggplot2) library(compare)
本次实验数据来源于DATA.GOV,它是一份关于医院医保的索赔支出数据,数据从这里下载。本文使用jsonlite
包中的fromJSON
函数来下载该数据集的JSON格式数据。JSON是一个用于实现浏览器与服务器异步通信的常见数据格式,如果你能理解下述获取数据的代码行的话那非常好。这里有两篇关于使用jsonlite
包来处理JSON格式数据的入门教程—教程1和教程2。当然,如果你只关注于data.table
和dplyr
包的使用方法,你完全可以放心的运行下面前两行代码而忽略具体的细节。
spending=fromJSON("https://data.medicare.gov/api/views/nrth-mfg3/rows.json?accesstype=DOWNLOAD") names(spending) "Meta" "data" Meta=spending$Meta hospital_spending=data.frame(spending$data) colnames(hospital_spending)=make.names(Meta$view$columns$name) hospital_spending=select(hospital_spending,-c(sid:Meta)) glimpse(hospital_spending) Observations: 70598 Variables: $ Hospital.Name (fctr) SOUTHEAST ALABAMA MEDICAL CENT... $ Provider.Number. (fctr) 010001,010001,010001... $ State (fctr) AL,AL,AL... $ Period (fctr) 1 to 3 days Prior to Index Hos... $ Claim.Type (fctr) Home Health Agency,Hospice,I... $ Avg.Spending.Per.Episode..Hospital. (fctr) 12,1,6,160,462,0... $ Avg.Spending.Per.Episode..State. (fctr) 14,85,2,9,492,... $ Avg.Spending.Per.Episode..Nation. (fctr) 13,5,117,532,0... $ Percent.of.Spending..Hospital. (fctr) 0.06,0.01,0.03,0.84,... $ Percent.of.Spending..State. (fctr) 0.07,0.46,... $ Percent.of.Spending..Nation. (fctr) 0.07,0.00,0.58,... $ Measure.Start.Date (fctr) 2014-01-01T00:00:00,2014-01-0... $ Measure.End.Date (fctr) 2014-12-31T00:00:00,2014-12-3...
如上所示,导入的所有数据列都是因子型数据。下面我们将列中数据为数值的列改为数值型数据:
cols = 6:11; # 需要改变数据类型的列 hospital_spending[,cols] <- lapply(hospital_spending[,cols],as.character) hospital_spending[,as.numeric)
最后两列数据分别是数据收集的起始日期和结束日期。因此,我们需要使用lubridate
包来纠正这两列的数据类型:
cols = 12:13; # 需要纠正的两列 hospital_spending[,ymd_hms)
现在,我们可以检查下数据列是否是我们想要的数据类型:
sapply(hospital_spending,class) $Hospital.Name "factor" $Provider.Number. "factor" $State "factor" $Period "factor" $Claim.Type "factor" $Avg.Spending.Per.Episode..Hospital. "numeric" $Avg.Spending.Per.Episode..State. "numeric" $Avg.Spending.Per.Episode..Nation. "numeric" $Percent.of.Spending..Hospital. "numeric" $Percent.of.Spending..State. "numeric" $Percent.of.Spending..Nation. "numeric" $Measure.Start.Date "POSIXct" "POSIXt" $Measure.End.Date "POSIXct" "POSIXt"
创建data.table类型数据
使用data.table
函数创建data.table类型数据:
hospital_spending_DT = data.table(hospital_spending) class(hospital_spending_DT) "data.table" "data.frame"
选取数据集的某些列
对于选取数据列,我们可以使用dplyr
包中的select
函数。另一方面,我们只需在data.table
中指定对应的列名即可。
选取一个变量
选取“Hospital Name”列:
from_dplyr = select(hospital_spending,Hospital.Name) from_data_table = hospital_spending_DT[,.(Hospital.Name)]
现在,我们对比下dplyr
和data.table
给出的结果是否相同:
compare(from_dplyr,from_data_table,allowAll=TRUE) TRUE dropped attributes
删除一个变量
from_dplyr = select(hospital_spending,-Hospital.Name) from_data_table = hospital_spending_DT[,!c("Hospital.Name"),with=FALSE] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
我们也可以使用:=
函数来修改data.table
输入类型的引用。对copy()
函数所复制的输入对象得到的引用执行任何操作都不会对原始数据对象产生任何影响。如下所示:
DT=copy(hospital_spending_DT) DT=DT[,Hospital.Name:=NULL] "Hospital.Name"%in%names(DT)FALSE
我们也可以一次性删除多个变量:
DT=copy(hospital_spending_DT) DT=DT[,c("Hospital.Name","State","Measure.Start.Date","Measure.End.Date"):=NULL] c("Hospital.Name","Measure.End.Date") %in% names(DT) FALSE FALSE FALSE FALSE
选取多个变量
选取如下变量:“Hospital.Name”,“State”,“Measure.Start.Date”,“Measure.End.Date”
from_dplyr = select(hospital_spending,Hospital.Name,State,Measure.Start.Date,Measure.End.Date) from_data_table = hospital_spending_DT[,.(Hospital.Name,Measure.End.Date)] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
删除多个变量
现在,我们要删除hospital_spending数据框和data.table类型数据hospital_spending_DT中的变量Hospital.Name,State,Measure.Start.Date,Measure.End.Date:
from_dplyr = select(hospital_spending,-c(Hospital.Name,Measure.End.Date)) from_data_table = hospital_spending_DT[,!c("Hospital.Name","Measure.End.Date"),with=FALSE] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
dplyr
包中有contains()
,starts_with()
,ends_with()
三个函数,它们可以跟select()
函数一起结合使用。对于data.table
,我们则可以使用正则表达式。下面我们将选取所有列名包含字符“Date”的列,示例如下:
from_dplyr = select(hospital_spending,contains("Date")) from_data_table = subset(hospital_spending_DT,select=grep("Date",names(hospital_spending_DT))) compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes names(from_dplyr) "Measure.Start.Date" "Measure.End.Date"
重命名列名
setnames(hospital_spending_DT,c("Hospital","Start_Date","End_Date")) names(hospital_spending_DT) "Hospital" "Provider.Number." "State" "Period" "Claim.Type" "Avg.Spending.Per.Episode..Hospital." "Avg.Spending.Per.Episode..State." "Avg.Spending.Per.Episode..Nation." "Percent.of.Spending..Hospital." "Percent.of.Spending..State." "Percent.of.Spending..Nation." "Start_Date" "End_Date" hospital_spending = rename(hospital_spending,Hospital= Hospital.Name,Start_Date=Measure.Start.Date,End_Date=Measure.End.Date) compare(hospital_spending,hospital_spending_DT,allowAll=TRUE) TRUE dropped attributes
筛选数据集的某些行
对于数据集特定行的筛选,我们可以使用dplyr
包中的filter
函数,它通过可能包含正则表达式的逻辑语句来实现该功能。在data.table
中,我们只需使用逻辑语句就可以了。
对单个变量进行筛选
from_dplyr = filter(hospital_spending,State=='CA') # selecting rows for California from_data_table = hospital_spending_DT[State=='CA'] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
对多个变量进行筛选
from_dplyr = filter(hospital_spending,State=='CA' & Claim.Type!="Hospice") from_data_table = hospital_spending_DT[State=='CA' & Claim.Type!="Hospice"] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
from_dplyr = filter(hospital_spending,State %in% c('CA','MA',"TX")) from_data_table = hospital_spending_DT[State %in% c('CA',"TX")] unique(from_dplyr$State) CA MA TX compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
数据排序
我们使用dplyr
包中的arrange()
函数对数据行进行排序,可以实现对一个或多个变量的数据行进行排序。如果想实现降序,需使用如下代码所示的desc()
函数。以下示例演示了如何对数据行进行升序和降序排序:
升序
from_dplyr = arrange(hospital_spending,State) from_data_table = setorder(hospital_spending_DT,State) compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
降序
from_dplyr = arrange(hospital_spending,desc(State)) from_data_table = setorder(hospital_spending_DT,-State) compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
对多变量进行排序
以下代码实现了State变量升序,End_Date变量降序排序:
from_dplyr = arrange(hospital_spending,desc(End_Date)) from_data_table = setorder(hospital_spending_DT,-End_Date) compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
添加或更新列
在dplyr
包中,使用mutate()
函数来添加新列。在data.table
包中,我们可以使用:=
引用来添加或更新列:
from_dplyr = mutate(hospital_spending,diff=Avg.Spending.Per.Episode..State. - Avg.Spending.Per.Episode..Nation.) from_data_table = copy(hospital_spending_DT) from_data_table = from_data_table[,diff := Avg.Spending.Per.Episode..State. - Avg.Spending.Per.Episode..Nation.] compare(from_dplyr,allowAll=TRUE) TRUE sorted renamed rows dropped row names dropped attributes
from_dplyr = mutate(hospital_spending,diff1=Avg.Spending.Per.Episode..State. - Avg.Spending.Per.Episode..Nation.,diff2=End_Date-Start_Date) from_data_table = copy(hospital_spending_DT) from_data_table = from_data_table[,c("diff1","diff2") := list(Avg.Spending.Per.Episode..State. - Avg.Spending.Per.Episode..Nation.,diff2=End_Date-Start_Date)] compare(from_dplyr,allowAll=TRUE) TRUE dropped attributes
数据汇总
我们可以使用dplyr
包中的summarise()
函数来创建概括性统计量:
summarize(hospital_spending,mean=mean(Avg.Spending.Per.Episode..Nation.)) mean 1820.409 hospital_spending_DT[,.(mean=mean(Avg.Spending.Per.Episode..Nation.))] mean 1820.409 summarize(hospital_spending,mean=mean(Avg.Spending.Per.Episode..Nation.), maximum=max(Avg.Spending.Per.Episode..Nation.), minimum=min(Avg.Spending.Per.Episode..Nation.), median=median(Avg.Spending.Per.Episode..Nation.)) mean maximum minimum median 1820.409 20025 0 109 hospital_spending_DT[,.(mean=mean(Avg.Spending.Per.Episode..Nation.), maximum=max(Avg.Spending.Per.Episode..Nation.), minimum=min(Avg.Spending.Per.Episode..Nation.), median=median(Avg.Spending.Per.Episode..Nation.))] mean maximum minimum median 1820.409 20025 0 109
当然,我们也可以对各分组的数据块分别求概述性统计量。在dplyr
中使用group_by()
函数,data.table
中指定by
参数即可:
head(hospital_spending_DT[,.(mean=mean(Avg.Spending.Per.Episode..Hospital.)),by=.(Hospital)])
mygroup= group_by(hospital_spending,Hospital) from_dplyr = summarize(mygroup,mean=mean(Avg.Spending.Per.Episode..Hospital.)) from_data_table=hospital_spending_DT[,by=.(Hospital)] compare(from_dplyr,allowAll=TRUE) TRUE sorted renamed rows dropped row names dropped attributes
我们也可以对多个分组条件进行分组计算:
head(hospital_spending_DT[, by=.(Hospital,State)])
mygroup= group_by(hospital_spending,Hospital,State) from_dplyr = summarize(mygroup,by=.(Hospital,State)] compare(from_dplyr,allowAll=TRUE) TRUE sorted renamed rows dropped row names dropped attributes
链式操作
在dplyr
和data.table
包中,我们可以使用链式操作来实现代码的连续性。在dplyr
中,使用magrittr
包中的%>%
管道函数非常酷。%>%
的功能是用于实现将一个函数的输出传递给下一个函数的第一个参数。在data.table
中,我们可以使用%>%
或[
来实现链式操作。
from_dplyr=hospital_spending %>% group_by(Hospital,State) %>% summarize(mean=mean(Avg.Spending.Per.Episode..Hospital.)) from_data_table=hospital_spending_DT[,allowAll=TRUE) TRUE sorted renamed rows dropped row names dropped attributes
hospital_spending %>% group_by(State) %>% summarize(mean=mean(Avg.Spending.Per.Episode..Hospital.)) %>% arrange(desc(mean)) %>% head(10) %>% mutate(State = factor(State,levels = State[order(mean,decreasing =TRUE)])) %>% ggplot(aes(x=State,y=mean))+geom_bar(stat='identity',color='darkred',fill='skyblue')+ xlab("")+ggtitle('Average Spending Per Episode by State')+ ylab('Average')+ coord_cartesian(ylim = c(3800,4000))
hospital_spending_DT[, by=.(State)][order(-mean)][1:10] %>% mutate(State = factor(State,decreasing =TRUE)])) %>% ggplot(aes(x=State,4000))
总结
在本篇文章,我们展示了使用data.table
和dplyr
包来执行相同的任务。它们有各自的长处。dplyr
包的语法更加优雅,提供了更易于人类所能理解的自然语言。data.table
包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table
在某些情况下执行速度更快,在性能和内存受限制的情况下data.table
或许是首选方案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。