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

时间:2012-01-24 17:59:54

标签: python r join data.table pandas

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

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

Comparison

以下是用于对各种套餐进行基准测试的R codePython code

3 个答案:

答案 0 :(得分:189)

pandas更快的原因是因为我提出了一个更好的算法,使用a fast hash table implementation - klib和C / Cython非常谨慎地实现,以避免不可向量化部分的Python解释器开销。我的演示文稿中详细描述了该算法:A look inside pandas design and development

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

我还要补充说,熊猫的内部设计' DataFrame比R的data.frame(内部数组列表)更适合这些操作。

答案 1 :(得分:116)

当唯一字符串(级别)的数量很大时,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)快速流行连接(roll=TRUE)a.k.a.最后一次观察结转。

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


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

  • 删除内部函数sortedmatch()并替换为chmatch()        将i级别与“factor”类型的列匹配为x级别时这个        初步步骤导致(已知)数量显着减速        因子列的水平很大(例如> 10,000)。加剧了        正如Wes McKinney所证明的那样,加入四个这样的柱子的测试        (Python包Pandas的作者)。匹配100万个字符串        例如,其中600,000是独特的,现在从16s减少到0.5s。

该版本也是:

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

  • 新功能chmatch()和%chin%,match()的更快版本 和字符向量的百分比%。 R的内部字符串缓存是 利用(没有建立哈希表)。它们的速度提高了约4倍 比?chmatch中的例子匹配()。

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


但正如我最初写的那样:

  

data.table考虑了时间序列合并。两个方面:i)   多列有序键,例如(id,datetime)ii)快速流行   加入(roll=TRUE)a.k.a.最后一次观察结果。

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

总之,这个特殊的双字符列测试突出显示的闪烁速度差异超过10,000个唯一字符串现在不应该那么糟糕,因为已知的问题已得到解决。

答案 2 :(得分:3)

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

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

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


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

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

  

q1:LHS内部加入RHS- (整数)
  q2:LHS内部加入RHS-medium整数
  q3:LHS 外部以整数形式加入RHS-介质
  问题4:LHS内部加入因子(绝对)
  q5:LHS内部加入RHS- 整数

RHS桌子有3种尺寸

  • 转换为LHS / 1e6的大小
  • 中等转换为LHS / 1e3的大小
  • 转换为LHS的大小

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


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

熊猫0.25.3于2019年11月1日发布
data.table 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 |
+-----------+--------------+----------+--------+