python - Pandas MultiIndex 单级查找比其他访问模式慢得多

标签 python pandas

我有这个独立的代码片段,应该是不言自明的:

import string
import itertools
import numpy as np
import timeit

index = list(itertools.product(range(100_000), string.ascii_uppercase))

df = pd.DataFrame(index, columns=['i', 'p'])
df['n'] = np.random.randn(len(df))
df_2 = df.set_index('i', drop=False)
df = df.set_index(['i', 'p'], drop=False)

print('One level multiindex loc', timeit.timeit(lambda: df.loc[1000], number=100))
print('Search by column',         timeit.timeit(lambda: df[df.i == 1000], number=100))
print('Non unique index loc',     timeit.timeit(lambda: df_2.loc[1000], number=100))

结果:

One level multiindex loc 0.8600521469925297
Search by column 0.23243567100143991
Non unique index loc 0.03276521500083618

我需要根据 i 的值(在本例中为 1000)获取行组,并且我正在研究不同的访问模式。我完全不明白的是,为什么通过 MultiIndex 的第一级查找如此缓慢?我理解 MultiIndex 的概念是因为如果您遵循层次结构,它会很快。

编辑结果因 pandas 版本而异,现在看起来 pandas 1.1.0 中的 MultiIndex 有一些问题。

以下是 0.25 的结果:

print('One level multiindex loc 1', timeit.timeit(lambda: df.loc[1000], number=10000))
print('One level multiindex loc 2', timeit.timeit(lambda: df.loc[(1000, ), :], number=10000))
print('Search by column',           timeit.timeit(lambda: df[df.i == 1000], number=10000))
print('Non unique index loc',       timeit.timeit(lambda: df_2.loc[1000], number=10000))

One level multiindex loc 1 3.5869441789999996
One level multiindex loc 2 4.696559950999983
Search by column 26.05316364800001
Non unique index loc 2.409704655000013

pandas==1.1.0 的 10000 次重复比较:

One level multiindex loc 1 74.58197712
One level multiindex loc 2 74.65480156499996
Search by column 26.241522830999997
Non unique index loc 0.5789623329999927

pandas==1.0.5:

One level multiindex loc 1 75.16352942799999
One level multiindex loc 2 81.75229192099998
Search by column 25.121312993000004
Non unique index loc 2.481764503999983

最佳答案

我需要更新我的答案,因为一些额外的时间显示完全不同的结果:

import string
import itertools
import numpy as np
import timeit

index = list(itertools.product(range(100_000), string.ascii_uppercase))

df = pd.DataFrame(index, columns=['i', 'p'])
df['n'] = np.random.randn(len(df))
df_2 = df.set_index('i', drop=False)
df = df.set_index(['i', 'p'], drop=False)
df3 = df.copy().sort_index(level=0)

print('One level multiindex loc with tuple', timeit.timeit(lambda: df.loc[(1000, )], number=100))
print('One level multiindex loc', timeit.timeit(lambda: df.loc[1000], number=100))
print('Explicitly sorted one level multiindex loc', timeit.timeit(lambda: df3.loc[(1000, )], number=100))
print('Explicitly sorted one level multiindex loc with tuple', timeit.timeit(lambda: df3.loc[1000], number=100))
print('Search by column',         timeit.timeit(lambda: df[df.i == 1000], number=100))
print('Non unique index loc',     timeit.timeit(lambda: df_2.loc[1000], number=100))

# One level multiindex loc with tuple 0.05624850000003789
# One level multiindex loc 0.029734599999983402
# Explicitly sorted one level multiindex loc 0.03403290000005654
# Explicitly sorted one level multiindex loc with tuple 0.028620700000146826
# Search by column 0.5066366999999445
# Non unique index loc 0.0468722999999045

我的 Pandas pd.__version__ == 1.0.5

从版本 1.0.5 到 1.1.0 似乎有一些性能回归。

显式排序索引似乎可以提高索引速度,因此 MultiIndex loc 是最快的方法。我不知道内部发生了什么,但即使是未明确排序的 df.index 也会显示 df.index.get_level_values(0).is_monotonic_increasing == True ,所以它应该像排序索引一样处理。也许 pandas 核心开发团队的某个人可以阐明一些问题?

关于python - Pandas MultiIndex 单级查找比其他访问模式慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63374659/

相关文章:

python - 从 python 中的函数更新 ipywidget 下拉列表

python - 将 python 字符串索引转换为日期时间索引

python - 如何将多个 csv 文件中的行复制到 pandas 中的新文件?

Pandas 0.21.1 - DataFrame.replace 递归错误

python - 使用 agg & join 对一列进行分组,但仅基于唯一值

python - 使用 win32com 设置属性

python - 使用 argparse 传递以减号 (-) 开头的参数值

python - 给定一个对象,如何获取在运行时调用的绑定(bind)方法列表

python - 如何使用 python 终止/重置现有的 tcp 连接?

performance - Pandas to_excel-如何使其更快