快速熊猫过滤

时间:2014-02-12 20:28:03

标签: python pandas

如果名称列条目在给定列表中有一个项目,我想过滤一个pandas数据框。

这里有一个DataFrame

x = DataFrame(
    [['sam', 328], ['ruby', 3213], ['jon', 121]], 
    columns=['name', 'score'])

现在假设我们有一个列表['sam', 'ruby'],我们想要找到名称在列表中的所有行,然后对得分求和。

我的解决方案如下:

total = 0
names = ['sam', 'ruby']
for name in names:
     identified = x[x['name'] == name]
     total = total + sum(identified['score'])

然而,当数据帧变得非常大,并且名称列表也变得非常大时,一切都非常慢。

有没有更快的替代方案?

由于

3 个答案:

答案 0 :(得分:12)

尝试使用isin(感谢DSM在此loc建议ix):

In [78]: x = pd.DataFrame([['sam',328],['ruby',3213],['jon',121]], columns = ['name', 'score'])

In [79]: names = ['sam', 'ruby']

In [80]: x['name'].isin(names)
Out[80]: 
0     True
1     True
2    False
Name: name, dtype: bool

In [81]: x.loc[x['name'].isin(names), 'score'].sum()
Out[81]: 3541

CT朱建议使用np.in1d更快的替代方案:

In [105]: y = pd.concat([x]*1000)
In [109]: %timeit y.loc[y['name'].isin(names), 'score'].sum()
1000 loops, best of 3: 413 µs per loop

In [110]: %timeit y.loc[np.in1d(y['name'], names), 'score'].sum()
1000 loops, best of 3: 335 µs per loop

答案 1 :(得分:5)

如果您的数据重复了很多值,请尝试对该列使用“分类”数据类型,然后应用布尔过滤。比使用索引灵活得多,至少在我的情况下,速度要快得多。

data = pd.read_csv('data.csv', dtype={'name':'category'})
data[(data.name=='sam')&(data.score>1)]

names=['sam','ruby']    
data[data.name.isin(names)]

对于我在 pandas 1.2 中使用的约 1500 万行、约 20 万个唯一术语数据集,%timeit 结果是:

  • 对象列上的布尔过滤器:608 毫秒
  • .loc 过滤器在与索引相同的对象列上:281ms
  • 与“分类”类型相同的对象列上的布尔过滤器:16ms

从那里,添加 .sum() 或您正在寻找的任何聚合函数。

答案 2 :(得分:0)

如果我需要在一个字段上进行搜索,我注意到,如果我将DataFrame的索引更改为搜索字段,它将极大地帮助您。对于我的搜索和查找要求之一,我的性能提高了约 500%

因此,在您的情况下,可以使用以下名称进行搜索和过滤。

df = pd.DataFrame([['sam', 328], ['ruby', 3213], ['jon', 121]], 
                 columns=['name', 'score'])
names = ['sam', 'ruby']

df_searchable = df.set_index('name')

df_searchable[df_searchable.index.isin(names)]