我有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
中为每个唯一元素返回一行)。
答案 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