超高性能数据处理包data.table

浏览: 1430

作者简介

张丹,前况客创始人兼CTO、作家10年IT编程背景,多项SUN及IBM技术认证,精通多种开发语言,具有十分丰富的大数据处理经验,同时熟悉金融二级市场、交易规则和投研体系,著有《R的极客理想-工具篇》、《R的极客理想-高级开发篇》。前言在R语言中,我们最常用的数据类型是data.frame,绝大多数的数据处理的操作都是围绕着data.frame结构来做的。用data.frame可以很方便的进行数据存储和数据查询,配合apply族函数对数据循环计算,也可也用plyr, reshape2, melt等包对数据实现切分、分组、聚合等的操作。在数据量不太大的时候,使用起来很方便。但是,用data.frame结构处理数据时并不是很高效,特别是在稍大一点数据规模的时候,就会明显变慢。

data.table其实提供了套和data.frame类似的功能,特别增加了索引的设置,让数据操作非常高效,可能会提升1-2数量级。本章就将data.table包的使用方法。

目录1.     data.table包介绍2.     data.table包的使用3.     data.table包性能对比

1. data.table包介绍

data.table包是一个data.frame的扩展工具集,可以通过自定义keys来设置索引,实现高效的数据索引查询、快速分组、快速连接、快速赋值等数据操作。data.table主要通过二元检索法大大提高数据操作的效率,它也兼容适用于data.frame的向量检索法。同时,data.table对于大数据的快速聚合也有很好的效果,官方介绍说对于 100GB规模内存数据处理,运行效率还是很好的。那么,就让我们试验一下吧。

data.table项目地址:https://cran.r-project.org/web/packages/data.table/

本文所使用的系统环境

·        Win10 64bit

·        R: 3.2.3 x86_64-w64-mingw32/x64 b4bit

data.table包是在CRAN发布的标准库,安装起来非常简单,2条命令就可以了。


2. data.table包的使用

接下来,开始用data.table包,并熟悉一下data.table包的基本操作。

2.1 data.table创建数据集

通常情况,我们用data.frame创建一个数据集时,可以使用下面的语法。


对于data.table来说,创建一个数据集是和data.frame同样语法。


检查df, dt两个对象的类型,可以看到data.table是对data.frame的扩展类型。


如果data.table仅仅是对data.frame的做了S3的扩展类型,那么data.table是不可能做到对data.frame从效率有极大的改进的。通过检查data.table代码的结构定义,我们发现,

data.table的代码定义中并没有使用data.frame结构的依赖的代码,我们可以确认data.tabledata.frame的底层结果是不一样的。

那么为什么从刚刚用class函数检查data.table对象时,会看到data.tabledata.frame的扩展关系呢?这里就要了解R语言中对于S3面向对象系统的结构设计了,关于S3的面向对象设计,请参考文章R语言基于S3的面向对象编程(http://blog.fens.me/r-class-s3/)

2.2 data.tabledata.frame相互转换

如果想把data.frame对象和data.table对象进行转换,转换的代码是非常容易的,直接转换就可以了。

从一个data.frame对象转型到data.table对象。


从一个data.table对象转型到data.frame对象。


2.3 data.table进行查询

由于data.table对用户使用上是希望和data.frame的操作尽量相似,所以适用于data.frame的查询方法基本都适用于data.table,同时data.table自己具有的一些特性,提供了自定义keys来进行高效的查询。

下面先看一下,data.table基本的数据查义方法。


按行或按列查询


上面的操作,不管是用索引值,== $ 都是data.frame操作一样的。下面我们取data.table特殊设计的keys来查询。


按照自定义的索引进行查询。


从上面的代码测试中我们可以看出,在定义了keys后,我们要查询的时候就不用再指定列了,默认会把方括号中的第一位置留给keys,作为索引匹配的查询条件。从代码的角度,又节省了一个变量定义的代码。同时,可以用mult参数,对数据集增加过滤条件,让代码本身也变得更高效。如果查询的值,不是索引列包括的值,则返回NA

2.4 data.table对象进行增、删、改操作

data.table对象增加一列,可以使用这样的格式 data.table[, colname := var1]



data.table对象删除一列时,就是给这列赋值为空,使用这样的格式 data.table[, colname := NULL]。我们继续使用刚才创建的dt对象。


修改data.table对象的值,就是通过索引定位后进行值的替换,通过这样的格式 data.table[condition, colname := 0]。我们继续使用刚才创建的dt对象。


2.5 data.table的分组计算

基于data.frame对象做分组计算时,要么使用apply函数自己处理,要么用plyr包的分组计算功能。对于data.table包本身就支持了分组计算,很像SQLgroup by这样的功能,这是data.table包主打的优势。

比如,按a列分组,并对b列按分组求和。


2.6 多个data.table的连接操作

在操作数据的时候,经常会出现2个或多个数据集通过一个索引键进行关联,而我们的算法要把多种数据合并到一起再进行处理,那么这个时候就会用的数据的连接操作,类似关系型数据库的左连接(LEFT JOIN)

举个例子,学生考试的场景。按照ER设计方法,我们通常会按照实体进行数据划分。这里存在2个实体,一个是学生,一个是成绩。学生实体会包括,学生姓名等的基本资料,而成绩实体会包括,考试的科目,考试的成绩。

假设有6个学生,分别参加AB两门考试,每门考试得分是不一样的。



通过学生ID,把学生和考试成绩2个数据集进行连接。


最后我们会看到,两个数据集的结果合并在了一个结果数据集中。这样就完成了,数据连接的操作。从代码的角度来看,1行代码要比用data.frame去拼接方便的多。


3. data.table包性能对比

现在很多时候我们需要处理的数据量是很大的,动辄上百万行甚至上千万行。如果我们要使用R对其进行分析或处理,在不增加硬件的条件下,就需要用一些高性能的数据包进行数据的操作。这里就会发现data.table是非常不错的一个选择。

3.1 data.tabledata.frame索引查询性能对比

我们先生成一个稍大数据集,包括2xy分别用英文字母进行赋值,100,000,004行,占内存大小1.6G。分别比较data.frame操作和data.table操作的索引查询性能耗时。

使用data.frame创建数据集。


再使用data.table创建数据集。


从上面的测试来看,创建对象时,data.tabledata.frame显著的高效,而查询效果则并不明显。我们对data.table数据集设置索引,试试有索引查询的效果。


设置索引列后,按索引进行查询,无CPU耗时。震惊了!!


3.2 data.tabledata.frame的赋值性能对比

对于赋值操作来说,通常会分为2个动作,先查询再值替换,对于data.framedata.table都是会按照这个过程来实现的。从上一小节中,可以看到通过索引查询时data.tabledata.frame明显的速度要快,对于赋值的操作测试,我们就要最好避免复杂的查询。

x列值为R的行,对应的y的值进行赋值。首先测试data.frame的计算时间。


计算data.table的赋值时间。


通过对比data.tabledata.frame的赋值测试,有索引的data.table性能优势是非常明显的。我们增大数据量,再做一次赋值测试。


对于增加数据量后data.table,要比data.frame的赋值快更多倍。


3.3 data.tabletapply分组计算性能对比

再对比一下data.table处理数据和tapply的分组计算的性能。测试同样地只做一个简单的计算设定,比如,对一个数据集按x列分组对y列求和。


对于40mb左右的数据来说,tapplydata.table要快,那么我增加数据集的大小,给size*10再测试一下。


对于400mb的数据来说,data.table的计算性能已经明显优于tapply了,再把数据时增加让size*5


对于2G左右的数据来说,tapply总耗时到了16秒,而data.table1.6秒,从2个的测试来说,大于400mb数据时CPU耗时是线性的。

把上几组测试数据放到一起,下图所示。


通过上面的对比,我们发现data.table包比tapply10倍,比data.frame赋值操作快30倍,比data.frame的索引查询快100倍,绝对是值得花精力去学习的一个包。

赶紧用data.table包去优化你的程序吧!

文章出处:http://blog.fens.me/r-data-table/转载请联系作者。



推荐 1
本文由 菜鸟数据岛 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册