Python 熊猫:基于重复索引值加速df.loc

Python 熊猫:基于重复索引值加速df.loc,python,performance,pandas,dataframe,Python,Performance,Pandas,Dataframe,我有熊猫数据框 import pandas as pd import numpy as np df = pd.DataFrame({ 'x': ['a', 'b', 'c'], 'y': [1, 2, 2], 'z': ['f', 's', 's'] }).set_index('x') 我想根据选择数组中索引(x)的值从中选择行 selection = ['a', 'c', 'b', 'b', 'c', 'a'] 使用df.loc可获得正确的输出,如下所示 out

我有熊猫数据框

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'x': ['a', 'b', 'c'],
    'y': [1, 2, 2],
    'z': ['f', 's', 's']
}).set_index('x')
我想根据选择数组中索引(
x
)的值从中选择行

selection = ['a', 'c', 'b', 'b', 'c', 'a']
使用
df.loc
可获得正确的输出,如下所示

out = df.loc[selection]

我遇到的问题是df.loc在大数据帧(200-700万行)上运行非常慢。有没有办法加快这一行动?我研究了
eval()
,但它似乎不适用于像这样的硬编码索引值列表。我还考虑过使用
pd.DataFrame.isin
,但这会忽略重复值(在
选择中,每个唯一元素只返回一行)。

您可以尝试
合并

df = pd.DataFrame({
    'x': ['a', 'b', 'c'],
    'y': [1, 2, 2],
    'z': ['f', 's', 's']
})

df1 = pd.DataFrame({'x':selection})

In [21]: pd.merge(df1,df,on='x', how='left')
Out[21]: 
   x  y  z
0  a  1  f
1  c  2  s
2  b  2  s
3  b  2  s
4  c  2  s
5  a  1  f

使用
reindex
而不是
loc
,可以获得不错的加速比:

df.reindex(selection)
计时(版本0.17.0):

这两种方法采用不同的路径(因此速度不同)

loc
通过调用 这必然比简单(用于唯一值)更复杂


另一方面,
reindex
中的繁重工作似乎是由中的
take.*
函数完成的。为了构造新的数据帧,这些函数似乎速度更快。

您可以消除选择中的重复。@riotburn重复对于应用程序来说是必要的。如果索引位于选择中的某一行中,则选择该行时如何必要?无法执行
df.loc[列表(设置(选择))]
?不,复制品是故意的<代码>输出
是所需的输出。
>>> selection2 = selection * 100 # a larger list of labels
>>> %timeit df.loc[selection2]
100 loops, best of 3: 2.54 ms per loop

>>> %timeit df.reindex(selection2)
1000 loops, best of 3: 833 µs per loop