Pandas Date Groupby&Apply-性能改进

时间:2019-04-18 15:30:31

标签: python pandas numpy

我正在做一个半小时的分组约会,并申请在我的数据集上计算每日统计信息,但是速度很慢。有没有一种方法可以改善以下功能的性能?我已经读过关于向量化的知识,但不确定如何实现。

我已经使用了apply和transform来获得所需的输出,但是整整一年的数据大约需要2-3秒,我希望能更快地完成,因为我有很多数据。任何人都可以指出正确的方向吗?

import pandas as pd
import numpy as np
import timeit

# dummy data
date_range = pd.date_range('2017-01-01 00:00', '2018-01-01 00:00', freq='30Min')
df = pd.DataFrame(np.random.randint(2, 20, (date_range.shape[0], 2)), index=date_range, columns=['Electricity', 'Natural Gas'])

print(df.head())
print(df.shape)

t1 = timeit.default_timer()
onhour = df.groupby([pd.Grouper(freq='D')]).apply(lambda x: np.count_nonzero(
    x[x > x.quantile(0.05) + x.mean() * .1] >
    x.quantile(0.05) + 0.25 * (x.quantile(0.95)-x.quantile(0.05)),
    axis=0) / 2)

onhour = pd.DataFrame(
    onhour.values.tolist(),
    index=onhour.index,
    columns=df.columns)

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

t1 = timeit.default_timer()
onhour = df.groupby([pd.Grouper(freq='D')]).transform(lambda x: np.count_nonzero(
    x[x > x.quantile(0.05) + x.mean() * .1] >
    x.quantile(0.05) + 0.25 * (x.quantile(0.95)-x.quantile(0.05)),
    axis=0) / 2).resample('D').mean()

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

1 个答案:

答案 0 :(得分:2)

您已经在使用熊猫矢量化优化,因此您不会花费很多时间,但是一些技巧可以使您在1.5秒内获得成功。

1)使用agg

使用agg代替transformapply会得到更好的结果,因为you have the same computation for each column (electricity & gas)

2)保存分位数计算。

您正在计算5%分位数的3倍。我使用的是Python function而不是lambda,如果您添加了记忆化的分位数功能,它仍然可以使用lambda(它实际上可以帮助固定,但我敢肯定)。

def count_something(row):
    qt_df = row.quantile([0.05, 0.95])
    return np.count_nonzero(
        row[row > qt_df.loc[0.05] + row.mean() * .1] > qt_df.loc[0.05] + 0.25 * (qt_df.loc[0.95] - qt_df.loc[0.05]),
        axis=0) / 2

t1 = timeit.default_timer()

onhour = df.groupby([pd.Grouper(freq='D')]).agg(count_something)

print(f"start_time in {timeit.default_timer() - t1}")
print(onhour.head())

如果您真的想加快计算速度,并且有办法并行化或分布您的计算,我想您可以使用python dask,但我认为它不会改善您的问题。