熊猫:根据重复索引值加速df.loc

时间:2015-10-26 20:02:21

标签: python performance pandas dataframe

我有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 = df.loc[selection]

我遇到的问题是df.loc在大型DataFrame(2-7百万行)上的运行速度非常慢。有没有办法加快这个操作?我已查看eval(),但它似乎并不适用于像这样的索引值的硬编码列表。我还考虑过使用pd.DataFrame.isin,但是错过了重复值(仅在selection中为每个唯一元素返回一行)。

2 个答案:

答案 0 :(得分:4)

使用reindex代替loc

可以获得不错的加速
df.reindex(selection)

Timings(版本0.17.0):

>>> 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

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

loc通过调用来构建新的DataFrame get_indexer_non_unique这一点比简单的get_indexer更复杂(用于唯一值)。

另一方面,reindex中的辛勤工作似乎是由generated.pyx中的take_*功能完成的。为了构造新的DataFrame,这些函数看起来更快。

答案 1 :(得分:2)

您可以尝试merge

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