加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

工具 | R高效数据处理包dplyr和data.table,你选哪个?

发布时间:2021-03-06 14:06:57 所属栏目:大数据 来源:网络整理
导读:dplyr和data.table是R的两个高效数据处理包,这两个包有它们各自的优点。dplyr包的语法更加优雅,提供了更易于人类所能理解的自然语言。data.table包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table在某些情况下执行效率更高(见这里
副标题[/!--empirenews.page--]

工具 | R高效数据处理包dplyr和data.table,你选哪个?

dplyr和data.table是R的两个高效数据处理包,这两个包有它们各自的优点。dplyr包的语法更加优雅,提供了更易于人类所能理解的自然语言。data.table包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table在某些情况下执行效率更高(见这里)。在性能和内存受约束的情况,data.table包或许是首选的R包。关于dplyr和data.table包之间的对比可以参考StackOverflow和Quora。


背景介绍

在我的数据处理任务中,我算是使用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包的使用方法,你完全可以放心的运行下面前两行代码而忽略具体的细节。

工具 | R高效数据处理包dplyr和data.table,你选哪个?


如上所示,导入的所有数据列都是因子型数据。下面我们将列中数据为数值的列改为数值型数据:

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_data_table = hospital_spending_DT[,!c("Hospital.Name"),with=FALSE]

compare(from_dplyr,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
我们也可以使用:=函数来修改data.table输入类型的引用。对copy()函数所复制的输入对象得到的引用执行任何操作都不会对原始数据对象产生任何影响。如下所示:

DT=copy(hospital_spending_DT)
DT=DT[,Hospital.Name:=NULL]
"Hospital.Name"%in%names(DT)FALSE
我们也可以一次性删除多个变量:

FALSE FALSE FALSE FALSE?
选取多个变量

选取如下变量:“Hospital.Name”,“State”,“Measure.Start.Date”,“Measure.End.Date”

from_data_table = hospital_spending_DT[,.(Hospital.Name,Measure.End.Date)]
compare(from_dplyr,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
?删除多个变量

现在,我们要删除hospital_spending数据框和data.table类型数据hospital_spending_DT中的变量Hospital.Name,State,Measure.Start.Date,Measure.End.Date:

from_data_table = hospital_spending_DT[,!c("Hospital.Name","Measure.End.Date"),with=FALSE]
compare(from_dplyr,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
dplyr包中有contains(),starts_with(),ends_with()三个函数,它们可以跟select()函数一起结合使用。对于data.table,我们则可以使用正则表达式。下面我们将选取所有列名包含字符“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,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
对多个变量进行筛选
from_data_table = hospital_spending_DT[State=='CA' & Claim.Type!="Hospice"]

compare(from_dplyr,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,0);"> 数据排序
我们使用dplyr包中的arrange()函数对数据行进行排序,可以实现对一个或多个变量的数据行进行排序。如果想实现降序,需使用如下代码所示的desc()函数。以下示例演示了如何对数据行进行升序和降序排序:

升序
from_dplyr = arrange(hospital_spending,State)
from_data_table = setorder(hospital_spending_DT,State)
compare(from_dplyr,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
降序
from_data_table = setorder(hospital_spending_DT,-State)
compare(from_dplyr,62); line-height: 25.6px; white-space: normal; word-wrap: break-word !important;">
对多变量进行排序

以下代码实现了State变量升序,End_Date变量降序排序:
from_dplyr = arrange(hospital_spending,desc(End_Date))
from_data_table = setorder(hospital_spending_DT,-End_Date)
compare(from_dplyr,0);"> 添加或更新列

在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_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,0);"> 数据汇总

我们可以使用dplyr包中的summarise()函数来创建概括性统计量:

工具 | R高效数据处理包dplyr和data.table,你选哪个?

当然,我们也可以对各分组的数据块分别求概述性统计量。在dplyr中使用group_by()函数,data.table中指定by参数即可:

head(hospital_spending_DT[,.(mean=mean(Avg.Spending.Per.Episode..Hospital.)),by=.(Hospital)])

工具 | R高效数据处理包dplyr和data.table,你选哪个?

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

我们也可以对多个分组条件进行分组计算:


? ? ? ? ? ? ? ? ? ? ? ? ? by=.(Hospital,State)])

工具 | R高效数据处理包dplyr和data.table,你选哪个?

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中,我们可以使用%>%或[来实现链式操作。

工具 | R高效数据处理包dplyr和data.table,你选哪个?

工具 | R高效数据处理包dplyr和data.table,你选哪个?

工具 | R高效数据处理包dplyr和data.table,你选哪个?

总结

在本篇文章,我们展示了使用data.table和dplyr包来执行相同的任务。它们有各自的长处。dplyr包的语法更加优雅,提供了更易于人类所能理解的自然语言。data.table包的语法简洁,并且只需一行代码就可以完成很多事情。进一步地,data.table在某些情况下执行速度更快,在性能和内存受限制的情况下data.table或许是首选方案。

翻译整理 | 雪晴数据网
原文请参考Best packages for data manipulation in R
作者:Fisseha Berhane
文章来源:http://www.xueqing.tv/cms/article/213

(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读