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

Zac*_*ach 156 python join r pandas data.table

我最近遇到了python 的pandas库,根据这个基准测试执行非常快速的内存中合并.它甚至比R中的data.table包更快(我选择用于分析的语言).

为什么pandas这么快data.table?是因为python具有超过R的固有速度优势,还是有一些我不知道的权衡?有没有办法在data.table不诉诸merge(X, Y, all=FALSE)和执行内部和外部联接的情况下merge(X, Y, all=TRUE)

对照

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

Wes*_*ney 189

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

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

我还要补充一点,pandas的DataFrame的内部设计比R的data.frame(内部的数组列表)更适合这些操作.

  • 当然,现在你已经在python中找到了所有内容,它应该很容易转换成R;) (76认同)
  • 但是为什么有人想要呢?:) (37认同)
  • 嗨Wes--似乎你的`data.table`的结果主要由一个已被修复的bug驱动.您是否有机会重新运行基准测试并撰写更新的博客文章? (27认同)
  • 嗯...也许是因为他们希望R中的数据操作更快?只是猜猜:)) (9认同)
  • Zach确保你看看这个:https://github.com/Rdatatable/data.table/wiki/Benchmarks- :-Grouping (6认同)
  • 我是100!一个新的基准将是有用的,我是否在第100次投票中赢得了这个礼物? (4认同)
  • 更新的基准在这里,显示 1) data.table 即使对于“冷”分组也更快 2) pandas 不具备在 125GB 内存中使用 50GB 表进行分组所需的内存效率 https://h2oai.github。 io/db-基准/ (4认同)

Mat*_*wle 117

看起来Wes可能在data.table独特字符串(级别)的数量很大时发现了一个已知问题:10,000.

是否Rprof()揭示了通话中花费的大部分时间sortedmatch(levels(i[[lc]]), levels(x[[rc]])?这不是连接本身(算法),而是一个初步步骤.

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

pandas合并比data.table常规整数列更快吗?这应该是一种隔离算法本身与因子问题的方法.

此外,data.table还考虑了时间序列合并.两个方面:i)多列有序键,例如(id,datetime)ii)快速流行的join(roll=TRUE)也称为最后一次观察结转.

我需要一些时间来确认,因为这是我见过的第一个比较data.table.


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

  • 内部函数sortedmatch()在将i级别与"factor"类型的列匹配为x级别时删除并替换为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的内部字符串缓存(不构建哈希表).它们比?chmatch中的例子上的match()快4倍.

截至2013年9月,CRAN上的data.table为v1.8.10,我们正在开发v1.9.0.新闻现场更新.


但正如我最初写的,上面:

data.table时间序列合并的想法.两个方面:i)多列有序键,例如(id,datetime)ii)快速流行的join(roll=TRUE)也称为最后一次观察结转.

所以两个字符列的Pandas equi连接可能仍然比data.table快.因为它听起来像哈希结合两列.data.table不会对密钥进行哈希处理,因为它考虑了主要的有序连接.data.table中的"键"实际上只是排序顺序(类似于SQL中的聚簇索引;即,数据在RAM中的排序方式).例如,列表中是添加辅助密钥.

总之,由于已知问题已得到修复,因此具有超过10,000个唯一字符串的此特定双字符列测试突出显示的明显速度差异现在不应该那么糟糕.

  • 我没有使用这些库中的任何一个,但很高兴看到来自R侧的Matthew Dowle形状的建设性反应. (21认同)
  • @AndyHayden前段时间进行了改进.我将在NEWS项目中进行编辑.Wes选择了一个特定的测试(等于连接两个字符列),这个测试就是针对这个已知问题进行的.如果他选择了整数列,那就不一样了.如果他在会议上提出基准之前给了我一个抬头,那么我可以告诉他更多有关已知问题的信息. (14认同)
  • 如果您为一个相当大的实际数据集提供测试用例,我将很乐意运行基准测试.你也非常欢迎.我实际上还没有优化整数连接键情况的代码(把它放在我的待办事项列表中!),但是你可以期待比链接表示中的哈希表研究的字符串情况明显更好的性能. (5认同)
  • 这里有一些Rprof结果http://pastie.org/3258362.看起来有20-40%的时间花在sortedmatch上,具体取决于连接类型.将不得不再次查看整数列 - 我制作了一个pandas GitHub问题以提醒我优化该情况(https://github.com/wesm/pandas/issues/682) (3认同)
  • @MattDowle我希望有时能看到更新的基准! (2认同)

Mer*_*rik 36

这个话题已经有两年了,但在人们寻找熊猫和数据的比较时似乎是一个可能的地方.

由于这些都随着时间的推移而发展,我想在这里为感兴趣的用户发布一个相对较新的比较(从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)更快.

  • @Zach看到这个:https://github.com/szilard/benchm-databases,这也很好:https://speakerdeck.com/szilard/r-stories-from-the-trenches-budapest-r-meetup-八月-2015 (6认同)
  • @Zach 四年后,新的基准结果终于出现了,请参阅下面我的答案。 (2认同)

jan*_*cki 9

有很好的答案,特别是由提出问题的两种工具的作者提出的。马特的回答解释了问题中报告的案例,它是由错误引起的,而不是由合并算法引起的。第二天就修复了错误,这已经是 7 年前的事了。

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

我展示的时间来自db-benchmark项目,这是一个持续运行的可重现基准。它将工具升级到最新版本并重新运行基准测试脚本。它运行许多其他软件解决方案。如果您对 Spark、Dask 和其他少数人感兴趣,请务必查看链接。


截至目前......(仍有待实施:另外一个数据大小和另外5个问题)

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

q1:LHS 内连接 RHS- 整数
q2 :LHS 内连接 RHS-中整数
q3:LHS连接 RHS-中整数
q4 :LHS 内连接 RHS-中因子(分类)
q5:LHS 内连接 RHS-中整数 整数

RHS 桌子有 3 种不同的尺寸

  • 转化为 LHS/1e6 的大小
  • medium转换为 LHS/1e3 的大小
  • big转化为 LHS 的大小

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


截至目前(2019 年 11 月 2 日运行)

pandas 0.25.3 于 2019 年 11 月 1 日发布
data.table 0.12.7 (92abb70) 于 2019 年 11 月 2 日发布

以下计时以秒为单位,用于 LHS 的两种不同数据大小。列pd2dt增加了pandas比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 |
+-----------+--------------+----------+--------+
Run Code Online (Sandbox Code Playgroud)
  • 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 |
+-----------+--------------+----------+--------+
Run Code Online (Sandbox Code Playgroud)