ChatGPT解决这个技术问题 Extra ChatGPT

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

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

为什么 pandasdata.table 快这么多?是因为 python 比 R 具有固有的速度优势,还是有一些我不知道的权衡?有没有一种方法可以在 data.table 中执行内部和外部联接而不使用 merge(X, Y, all=FALSE)merge(X, Y, all=TRUE)

https://i.stack.imgur.com/0pCvh.png

这是用于对各种软件包进行基准测试的 R codePython code

@JoshuaUlrich:IIRC data.table 只是继承自 data.frame,但它依赖于 C 代码。
@Joshua“即使您在C中操作data.frames也很慢”是什么意思?那是相对于别的东西吗?慢什么?
@JoshuaUlrich 我刚刚注意到这条评论线索从未被搁置。所以要澄清一下:在这次讨论之后不久,set() 被添加到 data.table 中。与 := 非常相似,但在循环时避免了 [.data.table 的小开销,因此与 matrix 一样快。因此,data.frame 可以 像矩阵一样被操纵。基准是 here
我们能得到这个基准的更新版本吗?很明显,这个工作台实际上是一个边缘案例,现在已经修复了。鉴于我见过的所有基准测试都表明 data.table 更快,我想看看合并数是多少?
@statquant 我没有运行原始基准,但我真的很想看到 Wes 更新基准。

A
Alex Riley

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

data.table 的比较实际上有点有趣,因为 R 的 data.table 的全部意义在于它包含用于各种列的预计算索引,以加速数据选择和合并等操作。在这种情况下(数据库连接),pandas 的 DataFrame 包含 没有用于合并的预计算信息,可以说这是一个“冷”合并。如果我存储了连接键的分解版本,连接会明显更快——因为分解是该算法的最大瓶颈。

我还应该补充一点,pandas 的 DataFrame 的内部设计比 R 的 data.frame(它只是内部数组的列表)更适合这些类型的操作。


当然,既然你已经在 python 中搞清楚了,它应该很容易翻译成 R ;)
但为什么会有人想要呢? :)
嗯......也许是因为他们希望 R 中的数据操作更快?只是猜测:))
嗨,Wes - 您对 data.table 的结果似乎主要是由一个已修复的错误驱动的。您是否有机会重新运行基准测试并撰写更新的博客文章?
M
Matt Dowle

当唯一字符串(levels)的数量很大时,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) 也就是最后的观察结果。

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

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

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

在那个版本中还有:

现在允许在键中使用字符列,并且优先考虑因素。 data.table() 和 setkey() 不再强制字符为因子。因素仍然得到支持。实现 FR#1493、FR#1224 和(部分)FR#951。

新函数 chmatch() 和 %chin%,match() 和 %in% 用于字符向量的更快版本。使用了 R 的内部字符串缓存(没有构建哈希表)。它们比 ?chmatch 中的示例中的 match() 快约 4 倍。

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

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

data.table 考虑了时间序列合并。有两个方面:i)多列有序键,例如(id,datetime)ii)快速流行连接(roll = TRUE)也就是最后的观察结转。

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

总之,这个包含超过 10,000 个唯一字符串的特殊两字符列测试突出显示的明显速度差异现在应该不会那么糟糕,因为已知问题已得到修复。


如果您为相当大的、实际的数据集提供测试用例,我将很乐意运行基准测试。也非常欢迎你。实际上,我还没有优化整数连接键案例的代码(把它放在我的待办事项列表上!),但是你可以期望在链接演示文稿中使用哈希表研究的情况下,其性能比字符串案例要好得多。
我没有使用这些库中的任何一个,但很高兴看到 R 方面以 Matthew Dowle 的形式做出了建设性的回应。
这是一些 Rprof 结果 pastie.org/3258362。看起来有 20-40% 的时间花在 sortedmatch 上,具体取决于连接类型。将不得不再次查看整数列——我制作了一个 pandas GitHub 问题来提醒我优化这种情况(github.com/wesm/pandas/issues/682
@AndyHayden 前段时间进行了改进。我将在 NEWS 项目中进行编辑。 Wes 选择了一项针对该已知问题的特定测试(等于加入两个字符列)。如果他选择整数列,情况会有所不同。如果他在会议上介绍基准之前给了我一个提示,那么我可以告诉他更多关于已知问题的信息。
J
Jealie

这个话题已经有两年的历史了,但是当人们搜索 Pandas 和 data.table 的比较时,这似乎是一个可能的落脚点

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

想知道 Wes 和/或 Matt(顺便说一下,他们分别是 Pandas 和 data.table 的创建者并且都在上面发表过评论)是否也有任何新闻要添加到这里会很有趣。

- 更新 -

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

https://i.stack.imgur.com/dAnZO.png

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

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


我正要发这个!感谢您的补充。
@Zach 四年后终于出现了新的基准测试结果,请参阅下面的答案。
j
jangorecki

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

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

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

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

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

q1:整数上的 LHS 内连接 RHS-small q2:整数上的 LHS 内连接 RHS-medium q3:整数上的 LHS 外连接 RHS-medium q4:因子(分类)上的 LHS 内连接 RHS-medium q5:LHS 内连接 RHS-大整数

RHS 表有 3 种不同的尺寸

small 转换为 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 |
+-----------+--------------+----------+--------+

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 实现添加一列?
我认为去网站查看是件好事,即使是查看 R dt 与 pandas 也是如此。 pyDT 并不是原始问题的一部分。