为什么2012年Pandas在python中的合并速度比data.table在R中的合并速度快?


160

最近,我遇到了python 的pandas库,根据该基准,该库执行非常快的内存中合并。它甚至比R(我选择分析的语言)中的data.table包还要快。

为什么pandas要比这快得多data.table?是因为python相对于R具有固有的速度优势,还是我不了解一些折衷方案?有没有一种方法可以执行内部和外部联接data.table而无需使用merge(X, Y, all=FALSE)and merge(X, Y, all=TRUE)

比较方式

这是用于对各种软件包进行基准测试的R代码Python代码


10
@JoshuaUlrich:IIRC data.table只是继承自data.frame,但它依赖于底层的C代码。
digEmAll 2012年

4
@Joshua你的意思是“即使在C语言中操作data.frames也会很慢”?这与其他有关吗?又慢什么呢?
马特·道尔

12
@JoshuaUlrich我只是注意到这条评论线索从未被搁浅。因此,为澄清起见:在此讨论之后不久就set()添加了data.table。与循环非常类似,:=但避免了[.data.table循环时的小开销,因此速度与循环一样快matrix。因此,data.frame 可以像矩阵一样快地进行操作。基准在这里
马特·道尔

5
我们能否获得该基准测试的更新版本,很明显,该基准测试实际上是一个边缘案例,目前已经修复。鉴于我所看到的所有基准测试都表明data.table更快,所以我想看看合并编号是多少?
statquant

3
@statquant我没有运行原始基准,但是我非常希望看到Wes更新基准。
Zach 2016年

Answers:


120

data.table当唯一字符串(级别)的数量很大:10,000 时,Wes似乎发现了一个已知问题。

是否Rprof()显示通话中的大部分时间sortedmatch(levels(i[[lc]]), levels(x[[rc]])?这实际上不是联接本身(算法),而是第一步。

最近的努力涉及允许键中的字符列,这应该通过与R自己的全局字符串哈希表更紧密地集成来解决该问题。已经报告了一些基准测试结果,test.data.table()但是尚未连接代码以替换级别匹配的级别。

大熊猫的合并速度是否比data.table常规整数列快?那应该是一种隔离算法本身与因素问题的方法。

此外,data.table时间序列合并的初衷。这有两个方面:i)多列有序键,例如(id,datetime); ii)快速流行的连接(roll=TRUE),也称为上一个观察结转。

我需要一些时间来确认,因为这是我所看到的与之比较的第一个data.table


2012年7月发布的data.table v1.8.0的更新

  • 当将“因子”类型的列的i级与x级进行匹配时,内部函数sortedmatch()被删除并替换为chmatch()。当因子列的级别数很大(例如,> 10,000)时,此初步步骤导致(已知)显着的减慢。如Wes McKinney(Python软件包Pandas的作者)所演示的,在连接四个这样的列的测试中加剧了这种情况。例如,匹配的100万个字符串(其中600,000个是唯一的)现在从16s减少到0.5s。

在该版本中还包括:

  • 现在,键中允许使用字符列,并且首选将其分解。data.table()和setkey()不再强制字符分解。仍然支持因素。实现FR#1493,FR#1224和(部分)FR#951。

  • 新功能chmatch()和%chin%,用于字符向量的match()和%in%的更快版本。使用R的内部字符串缓存(不构建哈希表)。它们比fchmatch示例中的match()快约4倍。

截至2013年9月,data.table在CRAN上的版本为v1.8.10,我们正在开发v1.9.0。新闻是实时更新的。


但是正如我最初在上面写的:

data.table具有时间序列合并的初衷。这有两个方面:i)多列有序键,例如(id,datetime); ii)快速流行的连接(roll=TRUE),也称为上一个观察结转。

因此,两个字符列的熊猫等值连接可能仍比data.table快。由于听起来像是对合并的两列进行哈希处理。data.table不会对键进行哈希处理,因为它考虑了普遍的有序连接。data.table中的“键”实际上只是排序顺序(类似于SQL中的聚簇索引;即,这就是在RAM中对数据进行排序的方式)。例如,在列表上添加辅助键。

总而言之,由于已知问题已得到解决,因此由具有10,000个以上唯一字符串的特殊的两个字符的列测试所强调的明显的速度差异现在应该不会那么糟糕。


6
如果您为相当大的,实际的数据集提供测试用例,我将很乐意运行基准测试。您也非常欢迎您。我实际上还没有针对整数联接键大小写优化代码(把它放在我的待办事项列表上!),但是鉴于链接演示中的哈希表研究,您可以期望比字符串大小写具有更好的性能。
Wes McKinney 2012年

22
我不使用任何一个库,但很高兴看到R方面以Matthew Dowle的形式提出建设性的回应。
SlowLearner 2012年

3
这是一些Rprof结果pastie.org/3258362。看起来20-40%的时间都花在了sortedmatch中,具体取决于联接类型。将不得不寻找到整数列另一个时间-我做了一个熊猫GitHub的问题,提醒我来优化这种情况下,(github.com/wesm/pandas/issues/682
韦斯麦金尼

14
@AndyHayden在前一段时间进行了改进。我将在“新闻”项目中进行编辑。Wes选择了一项针对该已知问题的特定测试(相等于连接两个字符列)。如果他选择整数列,那就不一样了。如果他在会议上介绍基准测试之前先给我提神,那么我本可以告诉他更多有关已知问题的信息。
Matt Dowle 2013年

191

pandas更快的原因是因为我想出了一个更好的算法,该算法使用快速哈希表实现非常仔细地实现-klib和C / Cython,以避免不可向量化部分的Python解释器开销。在我的演示文稿中对该算法进行了详细描述:熊猫设计和开发的内幕

与之data.table比较实际上有点有趣,因为R的要点data.table是它包含用于各个列的预先计算的索引,以加快诸如数据选择和合并之类的操作。在这种情况下(数据库连接),pandas的DataFrame不包含用于合并的预先计算的信息,可以说这是“冷”合并。如果我存储了联接键的分解版本,则联接将明显更快-因为分解是该算法的最大瓶颈。

我还应该补充一点,熊猫的DataFrame的内部设计比R的data.frame(内部只是数组的列表)更适合于此类操作。


76
当然,既然您已经在python中弄清楚了,就应该很容易将其转换为R;)
hadley 2012年

37
但是,为什么有人会想要呢?:)
2012年

9
嗯……也许是因为他们希望R中的数据操作更快?只是猜测:))
lebatsnok

28
嗨,韦斯(Hi Wes)-您的结果似乎data.table主要是由自此以来已修复的错误所驱动。您是否有可能重新运行基准测试并撰写更新的博客文章?
2014年

6
Zach确保您检查出以下内容:github.com/Rdatatable/data.table/wiki/Benchmarks
Merik

37

这个话题已经有两年历史了,但是当人们寻找熊猫和数据的比较时,它似乎是一个着陆的地方。

由于这两种方法都随着时间的推移而发展,因此我想在此为感兴趣的用户发布一个相对较新的比较(2014年以来):https : //github.com/Rdatatable/data.table/wiki/Benchmarks- : -Grouping

有趣的是,Wes和/或Matt(分别是Pandas和data.table的创建者,并且都在上面发表了评论)是否也有任何新闻要补充。

-更新-

jangorecki在下面发布的评论包含一个我认为非常有用的链接:https : //github.com/szilard/benchm-databases

https://github.com/szilard/benchm-databases/blob/master/plot.png

该图描绘了不同技术的聚合和连接操作的平均时间(更低=更快;比较上次更新于2016年9月)。对我来说真的很有教育意义。

回到问题,R DT keyR DT参考R的data.table的键控/非键控风格,并且在本基准测试中碰巧比Python的Pandas(Py pandas)快。


1
我正要发布这个!感谢您的添加。
Zach 2015年


1
@Zach四年后终于出现了新的基准测试结果,请参阅下面的答案。
jangorecki

7

有很好的答案,特别是这两个工具的作者都提出了这个问题。马特(Matt)的答案解释了问题中报告的情况,该情况是由错误而非合并算法引起的。错误已在第二天(超过7年前)修复。

在我的回答中,我将提供一些data.table和pandas合并操作的最新时间。请注意,不包括plyr和基本R合并。

我正在介绍的时间来自db-benchmark项目,它是一个连续运行的可复制基准。它将工具升级到最新版本并重新运行基准脚本。它运行许多其他软件解决方案。如果您对Spark,Dask和其他一些产品感兴趣,请务必检查链接。


截至目前...(仍在实施:一个数据大小和五个问题)

我们测试了LHS表的2种不同数据大小。
对于这些数据大小,我们运行5个不同的合并问题。

Q1:LHS内部联接RHS- 整数
Q2:LHS内加入RHS的培养基上整数
Q3:LHS 加入RHS的培养基上整数
Q4:LHS内加入RHS的培养基上因子(分类)
Q5:LHS内部联接RHS- 整数

RHS桌子有3种尺寸

  • 转化为LHS / 1e6的大小
  • 介质转换为LHS / 1e3的大小
  • 转换为LHS的大小

在所有情况下,LHS和RHS之间大约有90%的匹配行,并且RHS连接列中没有重复项(没有笛卡尔积)。


截止到现在(2019年11月2日运行)

熊猫0.25.3于2019年11月1日发布数据
表0.12.7(92abb70)于2019年11月2日发布

对于LHS的两种不同数据大小,以下计时单位为秒。列pd2dt中添加了大熊猫比data.table慢多少倍的字段存储比率。

  • 0.5 GB LHS数据
+-----------+--------------+----------+--------+
| question  |  data.table  |  pandas  |  pd2dt |
+-----------+--------------+----------+--------+
| q1        |        0.51  |    3.60  |      7 |
| q2        |        0.50  |    7.37  |     14 |
| q3        |        0.90  |    4.82  |      5 |
| q4        |        0.47  |    5.86  |     12 |
| q5        |        2.55  |   54.10  |     21 |
+-----------+--------------+----------+--------+
  • 5 GB LHS数据
+-----------+--------------+----------+--------+
| question  |  data.table  |  pandas  |  pd2dt |
+-----------+--------------+----------+--------+
| q1        |        6.32  |    89.0  |     14 |
| q2        |        5.72  |   108.0  |     18 |
| q3        |       11.00  |    56.9  |      5 |
| q4        |        5.57  |    90.1  |     16 |
| q5        |       30.70  |   731.0  |     23 |
+-----------+--------------+----------+--------+

感谢您日后的更新!您能为data.table的R vs python实现添加一列吗?
扎克

1
我认为即使浏览R dt vs熊猫,也可以只访问网站并进行检查。pyDT确实不是最初问题的一部分。
jangorecki
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.