查询dataframe的最快方法

11

我想在一个大的Pandas数据帧(数百万行)上执行汇总操作(求和),这些操作是由若干个固定列(最多10列)上的条件确定的。这些列仅包含整数值。

我的问题是,我必须执行这个操作(查询+汇总)数千次(〜100,000次)。我认为关于聚合部分没有太多需要优化的内容,因为它只是一个简单的求和。有没有办法在我的条件列上建立一个“索引”,以加快每个查询的速度?


4
虽然我不是专家,但您能否发布一些关于条件的代码?您是否使用了短路运算中的all()或者and?您能否同时使用算术运算符来测试几个条件? - Roberto
2
你应该计时操作并查看实际花费的时间(例如,在IPython中使用“%prun / %timeit”)。Pandas中的许多操作在幕后使用“numexpr”,因此索引可能非常快。 - Jeff
8
在0.13版本中(已发布0.13rc1),有几个新功能可能会对你有用:http://pandas.pydata.org/pandas-docs/dev/enhancingperf.html#expression-evaluation-via-eval-experimental; 你也可以尝试使用内存中的HDFStore!http://pytables.github.io/cookbook/inmemory_hdf5_files.html(只需将附加的驱动程序参数传递给HDFStore即可运行)。 - Jeff
4
这是使用 DataFrame.query()DataFrame.eval() 的绝佳示例。请尝试它并告诉我们效果如何! - Phillip Cloud
1
请确保使用Cython化的"&"和"||"运算符。例如:df[(df['A'] == 1) & (df['B'] == 2) & (df['C'] == 3)]。这些运算符比使用"and"和"or"更快。 - Ryan G
2个回答

1
我会尝试使用以下方式:
假设您有以下数据框:
N = 10000000
df = pd.DataFrame({
    'A':np.random.binomial(1,0.5,N),
    'B':np.random.binomial(2,0.5,N),
    'nume1':np.random.uniform(0,1,N),
    'nume2':np.random.normal(0,1,N)})

然后执行这个操作

tmp = df[['A','B','nume1','nume2']].query('A > 0.5').groupby('B').sum().reset_index()[['B','nume1','nume2']]

是SQL的等价物

select B, sum(nume1),sum(nume2)
from df
where A > 0.5
group by B

在我的中等配置机器上(i7四核,16GB RAM),这个操作只需要不到一秒钟的时间(926毫秒,使用%timeit测试)。

希望这能有所帮助。


1
没有更多细节,很难回答你的问题。 您确实应该建立一个条件列的索引。
df['idx'] = (df['col1'] * df['col2']) ** (df['col3'] + df['col4']) * df['col5'] == 0.012
df = df.set_index('idx')

将您的条件重写为可索引列可能很困难。请记住,您可以将所有列设置为索引。
df = df.set_index(['col1', 'col2', 'col3', 'col4', 'col5' ...])

这份关于Pandas高级索引的文档可能会帮助您思考问题: http://pandas.pydata.org/pandas-docs/stable/indexing.html#multiindex-query-syntax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接