性能:Pandas index.intersection() 与设置交集

问题描述 投票:0回答:2

我想找到两个数据帧索引的交集。一种方法是使用内置的

pd.Index.intersection()
方法。如:

# Dummy data just to make an index with some common values
ix = pd.read_excel('canadacities.xlsx', index_col=0,).index

# Index A
ix_a = ix[0:500]

# Index B
ix_b = ix[200:700]

# Finding the intersection
%%timeit
common_index = ix_a.intersection(ix_b)
# 767 µs ± 10.1 µs per loop 

或者,我可以使用集合来完成相同的工作

%%timeit

# Alternative 2, use sets
common_index = list(set(ix_a) & set(ix_b))
# 103 µs ± 685 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

令我惊讶的是内部 pandas 方法被证明慢得多。即使我随后在选择数据帧中的公共行时包含结果索引,情况也是如此。原生Python索引生成和选择速度较慢...

%%timeit
common_index = ix_a.intersection(ix_b)
foo = df.loc[common_index, :]
# 2.81 ms ± 100 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

...比其更定制的对应物

%%timeit
common_index = list(set(ix_a) & set(ix_b))
foo = df.loc[common_index, :]
#1.65 ms ± 7.14 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

所以我的问题是:

  1. 为什么pandas内部方法比较慢?
  2. 较慢的方法有一些补偿优势吗?
python pandas performance
2个回答
4
投票

pandas 中的索引是一个 NumPy 数组。因此,对于集合操作,它的性能特征会比针对此类操作进行优化的 Python

set
更差 - 底层实现是哈希映射,这大大降低了 检查某个值是否在集合中的时间复杂度O(1).

对于 NumPy 数组优化是为了快速遍历,因此执行一个暗指其名称设置操作但实际上以非常不同的方式执行的操作不会那么快。

在您的特定情况下,好处可能在于调用一个方法的优雅,而不是使用乍一看更加神秘的表达式。


0
投票

接受的答案将 Pandas Index 等同于 NumPy Array 是错误的。实际上,Pandas 索引基于哈希表,这就是为什么它只能包含可哈希对象(或应该包含)。

Pandas 内部方法较慢,因为它没有针对相交无序索引进行优化。如果您查看 2024 年(版本 2.2)的源代码,您会发现

ix_a.intersection(ix_b)
进行了多次快速路径检查,然后默认构建从 ix_b 到 ix_a 的索引器(或其他方式,不确定)。换句话说,回答这个问题

ix_a
ix_b
有哪些共同点?

它首先回答问题

ix_a
的元素位于
ix_b
中的什么位置?

这是一个更困难的问题,需要做比需要更多的工作。

现在,如果您的索引是有序的(它们包含增加或减少的元素),那么

ix_a.intersection(ix_b)
将优于 Python 内置集合(在某些情况下肯定如此)。我想,Pandas 只是以“合并排序”方式遍历两个数组

© www.soinside.com 2019 - 2024. All rights reserved.