如果名称列条目在给定列表中有一个项目,我想过滤一个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'])
然而,当数据帧变得非常大,并且名称列表也变得非常大时,一切都非常慢。
有没有更快的替代方案?
由于
答案 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 结果是:
从那里,添加 .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)]