我最近遇到了 python 的 熊猫库,根据 这个基准,它执行非常快的内存合并。它甚至比 R (我用于分析的首选语言)中的 Data.table包还要快。
为什么 pandas比 data.table快那么多?是因为 Python 比 R 有一个固有的速度优势,还是有一些我没有意识到的权衡?有没有一种方法可以在 data.table中执行内部和外部连接,而不必求助于 merge(X, Y, all=FALSE)和 merge(X, Y, all=TRUE)?
pandas
data.table
merge(X, Y, all=FALSE)
merge(X, Y, all=TRUE)
下面是 R 代码和 Python 代码,用于对各种软件包进行基准测试。
熊猫比较快的原因是我提出了一个更好的算法,这个算法使用 一个快速哈希表实现-klib和 C/Cython非常小心地实现,以避免不可向量化部分的 Python 解释器开销。该算法在我的演示文稿 熊猫设计与开发一览中有详细描述。
与 data.table的比较实际上有一点有趣,因为 R 的 data.table的全部意义在于它包含用于各种列的 预先计算的索引,以加速诸如数据选择和合并之类的操作。在这种情况下(数据库联接) ,熊猫的 DataFrame 包含用于合并的 没有预先计算好的信息,所以可以说这是一个“冷”合并。如果我已经存储了连接键的因子分解版本,那么连接会快得多——因为因子分解是这种算法的最大瓶颈。
我还应该补充一点,大熊猫的 DataFrame 的内部设计比 R 的 data.frame (它只是一个内部数组列表)更适合这类操作。
当唯一字符串(水平)的数量很大时,Wes 似乎已经在 data.table中发现了一个已知的问题: 10,000。
Rprof()是否揭示了大部分的时间花费在呼叫 sortedmatch(levels(i[[lc]]), levels(x[[rc]])?这实际上不是连接本身(算法) ,而是一个初步步骤。
Rprof()
sortedmatch(levels(i[[lc]]), levels(x[[rc]])
最近的努力是允许键中有字符列,这应该通过更紧密地与 R 自己的全局字符串哈希表集成来解决这个问题。test.data.table()已经报告了一些基准测试结果,但是还没有将代码连接起来,以替换与级别匹配的级别。
test.data.table()
对于常规整数列,熊猫合并是否比 data.table快?这应该是一种隔离算法本身和因素问题的方法。
此外,data.table还考虑了 时间序列合并时间序列合并。两个方面: i)多列 命令键,如(id,datetime) ii)快速流行的联接(roll=TRUE)又名最后的观察结果。
roll=TRUE
我需要一些时间来确认,因为这是我第一次看到与 data.table的比较。
2012年7月发布的 data.table v1.8.0更新
在那份新闻稿中还提到:
现在允许在键中使用字符列,并且首选 Table ()和 setkey ()不再强制字符 因素。因素仍然得到支持。实施 FR # 1493,FR # 1224 以及(部分) FR # 951
新函数 chmatch ()和% chin% ,match ()的更快版本 字符向量为% 。 R 的内部字符串缓存为 使用(没有哈希表建立)。他们大约4倍的速度 在? chmatch 中的示例中,除了 match ()之外,还有更多的内容。
截至2013年9月,data.table 在 CRAN 上的版本是 v1.8.10,我们正在开发 v1.9.0。
但正如我最初所写的那样:
data.table考虑的是 时间序列合并时间序列合并,有两个方面: i) 多列 命令键,如(id,datetime) ii)快速流行 加入(roll=TRUE) ,也就是最后的观察结果。
因此,两个字符列的 Pandas equi 连接可能仍然比 data.table 快。因为它听起来像是两列合并后的哈希表。Table 不对键进行哈希,因为它考虑到了主流的有序连接。Table 中的“键”实际上就是排序顺序(类似于 SQL 中的聚集索引; 也就是说,这就是数据在 RAM 中的排序方式)。例如,在列表中添加辅助键。
总而言之,这个特殊的两字符列测试突出显示了超过10,000个唯一字符串的明显速度差异,现在应该没有那么糟糕了,因为已经解决了已知的问题。
这个话题已经有两年的历史了,但是当人们搜索“熊猫”和“数据表”的比较时,这个话题似乎是个不错的选择
由于这两者都随着时间的推移发生了变化,我想在这里为感兴趣的用户发布一个相对较新的比较(从2014年开始) : https://github.com/Rdatatable/data.table/wiki/Benchmarks-:-Grouping
我很想知道 Wes 和/或 Matt (顺便说一下,他们分别是熊猫和 data.table 的创建者,并且都在上面发表了评论)是否也有什么新闻要添加到这里。
——更新——
下面由 jangorecki 发表的评论包含一个我认为非常有用的链接: https://github.com/szilard/benchm-databases
这个图表描述了不同技术的聚合和连接操作的平均时间(更低 = 更快; 比较最近一次更新是在2016年9月)。对我来说真的很有教育意义。
回到这个问题,R DT key和 R DT引用了 R 的 data.table 的键控/非键控风格,并且在这个基准测试中比 Python 的 Pandas (Py pandas)更快。
R DT key
R DT
Py pandas
这两个工具的作者都给出了很好的答案。 Matt 的回答解释了问题中提到的情况,那是一个错误引起的,而不是合并算法。第二天就修好了,已经是七年前的事了。
在我的回答中,我将提供一些关于 data.table 和 anda 合并操作的最新时间。注意,不包括 plyr 和 baseR merge。
我提出的时间是来自 基准项目,一个持续运行的可重复性基准。它将工具升级到最新版本,并重新运行基准测试脚本。它运行许多其他的软件解决方案。如果你对 Spark 感兴趣,Dask 和其他一些人一定要检查链接。
到目前为止... (还有待实现: 一个数据大小和5个问题)
我们测试了 LHS 表的两种不同的数据大小。 对于每个数据大小,我们运行5个不同的合并问题。
Q1: 整数上的 LHS 内连接 RHS-很小 Q2: LHS 内连接 RHS-介质对整数 Q3: LHS 外面加入 RHS-介质整数 问题4: LHS 内部加入 RHS-介于 因子(分类) Q5: LHS 内连接 RHS-很大对整数
RHS 表有3种不同的尺寸
在所有情况下,LHS 和 RHS 之间约有90% 的匹配行,而且在 RHS 连接列中没有重复行(没有笛卡儿积)。
截至目前(2019年11月2日运行)
大熊猫0.25.3于2019年11月1日发布 表0.12.7(92abb70)
对于 LHS 的两种不同数据大小,以下计时以秒为单位。列 pd2dt添加了字段存储比率,即大熊猫比 data.table 慢多少倍。
pd2dt
+-----------+--------------+----------+--------+ | 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 | +-----------+--------------+----------+--------+
+-----------+--------------+----------+--------+ | 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 | +-----------+--------------+----------+--------+