问题:为什么2012年Pandas在python中的合并速度比data.table在R中的合并速度快?
最近,我遇到了python 的pandas库,根据该基准,该库执行非常快的内存中合并。它甚至比R(我选择分析的语言)中的data.table包还要快。
为什么pandas
要比这快得多data.table
?是因为python相对于R具有固有的速度优势,还是我不了解一些折衷方案?有没有一种方法可以执行内部和外部联接data.table
而无需使用merge(X, Y, all=FALSE)
and merge(X, Y, all=TRUE)
?
回答 0
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个以上唯一字符串的特殊的两个字符的列测试所强调的明显的速度差异现在应该不会那么糟糕。
回答 1
pandas更快的原因是因为我想出了一个更好的算法,该算法使用快速哈希表实现非常仔细地实现-klib和C / Cython,以避免不可向量化部分的Python解释器开销。在我的演示文稿中对该算法进行了详细描述:熊猫设计和开发的内幕。
与之data.table
比较实际上有点有趣,因为R的要点data.table
是它包含用于各个列的预先计算的索引,以加快诸如数据选择和合并之类的操作。在这种情况下(数据库连接),pandas的DataFrame不包含用于合并的预先计算的信息,可以说这是“冷”合并。如果我存储了联接键的分解版本,则联接将明显更快-因为分解是该算法的最大瓶颈。
我还应该补充一点,熊猫的DataFrame的内部设计比R的data.frame(内部只是数组的列表)更适合于此类操作。
回答 2
这个话题已经有两年历史了,但是当人们寻找熊猫和数据的比较时,它似乎是一个着陆的地方。
由于这两种方法都随着时间的推移而发展,因此我想在此为感兴趣的用户发布一个相对较新的比较(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
)快。
回答 3
有很好的答案,特别是这两个工具的作者都提出了这个问题。马特(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 |
+-----------+--------------+----------+--------+