为何2012年Python中的pandas合并比R中的data.table合并更快?
我最近发现了一个叫做 pandas 的Python库。根据 这个基准测试,它在内存中合并数据的速度非常快,甚至比R语言中的 data.table 包还要快(我通常用R语言来做分析)。
那么,为什么 pandas
比 data.table
快这么多呢?是因为Python本身比R快,还是说有我不知道的某种权衡?在 data.table
中,有没有办法在不使用 merge(X, Y, all=FALSE)
和 merge(X, Y, all=TRUE)
的情况下进行内连接和外连接?
4 个回答
这个话题已经有两年了,但看起来很多人搜索Pandas和data.table的比较时,可能会来到这里。
因为这两个工具随着时间的发展也在不断变化,所以我想在这里分享一个相对较新的比较(来自2014年),供感兴趣的朋友参考:https://github.com/Rdatatable/data.table/wiki/Benchmarks-:-Grouping
我也很想知道Wes和Matt(顺便提一下,他们分别是Pandas和data.table的创始人,并且在上面有评论)是否有新的消息可以分享。
-- 更新 --
下面的评论由jangorecki发布,里面有一个我认为非常有用的链接:https://github.com/szilard/benchm-databases
这个图表展示了不同技术在聚合和连接操作中的平均时间(时间越短,速度越快;比较数据最后更新于2016年9月)。对我来说,这个信息非常有帮助。
回到问题上,R DT key
和R DT
指的是R语言中data.table的有键和无键版本,在这个基准测试中,它们的速度比Python的Pandas(Py pandas
)要快。
pandas之所以更快,是因为我想出了一个更好的算法,并且这个算法是通过一种快速哈希表实现 - klib,用C语言和Cython精心实现的,这样可以避免Python解释器在一些不能向量化的部分带来的额外开销。这个算法在我的演讲中有详细描述:深入了解pandas的设计与开发.
与data.table
的比较其实挺有意思,因为R的data.table
的主要特点就是它为各种列预先计算了索引,这样可以加快数据选择和合并等操作。在这种情况下(数据库连接),pandas的DataFrame并没有使用任何预先计算的信息来进行合并,可以说这是一个“冷”合并。如果我存储了连接键的因子化版本,合并的速度会显著提高,因为因子化是这个算法最大的瓶颈。
我还要补充一点,pandas的DataFrame内部设计比R的data.frame更适合进行这些操作,因为后者内部只是一个数组的列表。
看起来Wes可能发现了一个在data.table
中已知的问题,这个问题出现在唯一字符串(levels)数量很大时,比如达到10,000个。
使用Rprof()
能否显示大部分时间都花在调用sortedmatch(levels(i[[lc]]), levels(x[[rc]])
上?这其实并不是连接操作本身(算法),而是一个前期步骤。
最近的努力是允许在关键字中使用字符列,这样可以通过更紧密地与R自己的全局字符串哈希表集成来解决这个问题。一些基准测试的结果已经通过test.data.table()
报告出来,但这些代码还没有连接到替换levels与levels的匹配。
对于普通整数列,pandas的合并速度是否比data.table
快?这应该是一个可以区分算法本身和因子问题的方法。
另外,data.table
考虑到了时间序列合并。这有两个方面:i) 多列有序关键字,比如(id, datetime) ii) 快速的主导连接(roll=TRUE
),也就是把最后一次观察结果带到前面。
我需要一些时间来确认,因为这是我第一次看到与data.table
的比较。
更新:data.table v1.8.0于2012年7月发布
- 内部函数sortedmatch()被移除,替换为chmatch(),用于匹配i的levels与x的levels,针对类型为'factor'的列。这个前期步骤在因子列的levels数量很大时(例如超过10,000)会导致显著的速度下降。在连接四个这样的列的测试中,这个问题更加明显,正如Python包Pandas的作者Wes McKinney所展示的那样。比如,匹配100万个字符串,其中60万个是唯一的,时间从16秒减少到0.5秒。
在这个版本中还有:
现在允许在关键字中使用字符列,并且优先使用字符列而不是因子。
data.table()
和setkey()
不再将字符强制转换为因子。因子仍然被支持。实现了FR#1493、FR#1224和(部分)FR#951。新函数chmatch()和%chin%,是match()和%in%的更快版本,专门用于字符向量。利用了R的内部字符串缓存(不再构建哈希表)。在?chmatch的示例中,它们的速度大约是match()的4倍。
截至2013年9月,data.table的版本是v1.8.10,正在开发v1.9.0。新闻是实时更新的。
但正如我最初所写的:
data.table
考虑到了时间序列合并。这有两个方面:i) 多列有序关键字,比如(id, datetime) ii) 快速的主导连接(roll=TRUE
),也就是把最后一次观察结果带到前面。
所以,两个字符列的Pandas等值连接可能仍然比data.table快。因为它听起来像是对这两个列进行了哈希处理。data.table不对关键字进行哈希,因为它考虑的是主导有序连接。在data.table中,“关键字”实际上就是排序顺序(类似于SQL中的聚集索引;也就是说,这就是数据在内存中的排序方式)。计划中还有添加二级关键字的功能。
总的来说,这个特定的两个字符列测试中,超过10,000个唯一字符串所突显的明显速度差异现在应该不会那么严重,因为已知的问题已经得到解决。