pandas:将两个 DataFrame 与已排序的 MultiIndex 连接起来,使得结果具有已排序的 MultiIndex

Posted

技术标签:

【中文标题】pandas:将两个 DataFrame 与已排序的 MultiIndex 连接起来,使得结果具有已排序的 MultiIndex【英文标题】:pandas: concatenate two DataFrames with sorted MultiIndexes such that result has a sorted MultiIndex 【发布时间】:2018-10-27 01:14:42 【问题描述】:

请告诉我如何将两个 DataFrame 与已排序的 MultiIndex 连接起来,以使结果具有已排序的 MultiIndex。

由于两者都是排序的,算法必须在两个 DataFrame 中的总行数方面具有线性复杂度(这是合并 2 个排序列表的复杂度,这实际上是问题就在这里)。

例子:

import pandas as pd
t1 = pd.DataFrame(data='i1':[0,0,1,1,2,2],
                        'i2':[0,1,0,1,0,1],
                        'x':[1.,2.,3.,4.,5.,6.])
t1.set_index(['i1','i2'], inplace=True)
t1.sort_index(inplace=True)
t2 = pd.DataFrame(data='i1':[0,0,1,1,2,2],
                        'i2':[2,3,2,3,2,3],
                        'x':[7.,8.,9.,10.,11.,12.])
t2.set_index(['i1','i2'], inplace=True)
t2.sort_index(inplace=True)
>>> print(t1)
         x
i1 i2     
0  0   1.0
   1   2.0
1  0   3.0
   1   4.0
2  0   5.0
   1   6.0

>>> print(t2)
          x
i1 i2      
0  2    7.0
   3    8.0
1  2    9.0
   3   10.0
2  2   11.0
   3   12.0

预期结果:

          x
i1 i2      
0  0    1.0
   1    2.0
   2    7.0
   3    8.0
1  0    3.0
   1    4.0
   2    9.0
   3   10.0
2  0    5.0
   1    6.0
   2   11.0
   3   12.0

感谢您的帮助!

【问题讨论】:

我认为对于您的特定用例不会有已经实施的答案。如果第二个索引级别的第二个框架始终包含比第一个框架更大的元素,则可以考虑按第一级“分组”并联系下一级的框架。但是,由于列表大小可能不同,并且我们可能没有在第二个索引级别上明确分隔值,因此排序算法总是会在这里进行完整排序。他们不会使用连接的第二级由两个有序列表组成的信息。 没有关于索引值的假设:唯一可以做出的假设(如果有帮助的话)是两个索引没有交集。 这意味着您必须在第二个键级别上实现合并步骤或合并排序。目前,这还没有在 pandas 中实现。因此,您需要在第一级拆分索引(顺便说一句,这对于分布式计算来说会很好),然后您需要自己应用合并步骤。但是,正如@coldspeed 在其中一个答案中提到的那样,理论上的性能增益可能会由于新实现中的开销而丢失,并且快速排序可能会更快。请问,您为什么需要这种复杂性? 我需要它来有效地处理非常大的数据集,即使在具有数百 GB RAM 的服务器上也无法放入内存。我想将数据分成更小的部分,当我从这些部分中进行选择时,我想通过算法有效地将它们合并到一个适合 RAM 并实际处理的 DataFrame 中。我尝试了数据的分布式计算,但到目前为止我对结果不是很满意。 我不认为 pandas 在这种情况下是正确的工具。你结账了吗?火花/pyskark呢?为什么不满意,太慢了? 【参考方案1】:

这是一个候选答案。我仍在努力确认它的算法效率。如果您有意见,请发表评论:

def linConcat(t1, t2):
    t = t1.reindex( index=t1.index.union(t2.index) )
    t.loc[t2.index,:] = t2
    return t
>>> linConcat(t1, t2)
          x
i1 i2      
0  0    1.0
   1    2.0
   2    7.0
   3    8.0
1  0    3.0
   1    4.0
   2    9.0
   3   10.0
2  0    5.0
   1    6.0
   2   11.0
   3   12.0

【讨论】:

你试过在更大的数据集上计时这个函数吗?我已根据您发布的数据对 t1.append(t2).sort_index() 进行了基准测试,并获得了相同的性能。 我确实在几 GB 的数据上对其进行了测试。似乎即使 'linConcat' 可能是 O(N),它仍然比 t1.append(t2).sort_index() 慢得多(可能是由于 Python 实现的 reindex 或 union 或 loc):~13确切地说,在我的测试中慢了几倍。需要更好地实现合并排序的 DataFrame。无论如何,这两个版本对我来说都太慢了。

以上是关于pandas:将两个 DataFrame 与已排序的 MultiIndex 连接起来,使得结果具有已排序的 MultiIndex的主要内容,如果未能解决你的问题,请参考以下文章

Pandas:将系列添加到按列排序的 DataFrame

Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接,以及自定义排序

将 MultiIndex DataFrame 格式从列排序到 Pandas 中的变量

pandas中dataframe索引排序实战:pandas中dataframe索引降序排序pandas中dataframe索引升序排序

短视频学习 - 4pandas之DataFrame简单使用

如何将列名排序到 Pandas Dataframe(分类数据)中的 bin 中