python - pandas 聚合中的自定义函数非常慢

标签 python pandas

我必须计算我拥有的数据集中移动窗口的变异系数(标准/平均值)。代码非常简单:

start_time = time.time()

channel_data = data[data['channel_id'] == ch].sort_values('datetime')
channel_data['datetime'] = pd.to_datetime(channel_data['datetime'],format='%Y-%m-%d %H:%M:%S').dt.floor('d')
channel_data = channel_data.set_index('datetime')

rolling_data = channel_data.rolling('{}D'.format(window)).agg({ 'val': coeff_of_var })

rolling_data = rolling_data.groupby(rolling_data.index.floor('d')).last()[window:]

print('Time needed: {} seconds'.format(time.time() - start_time))

我的问题是它非常慢。

coeff_of_var 可以是 scipy.stats.variation 的自定义函数,也可以是 lambda 函数 - 我都尝试过。我使用的自定义函数是

def coeff_of_var(series):
    return series.std() / series.mean()

data 是一个尺寸为 [3070584 行 x 5 列] 的 DataFrame。 channel_data 包含约 457710 行。

这段代码在一个循环内,并且花费了很长时间,以至于我不得不在第一次执行时间的print之前停止它......

我没有计算变异系数,而是尝试分别计算std和mean,即将第5行大括号中的函数替换为:['std', 'mean']。新行是:

std_rolling_data = channel_data.rolling('{}D'.format(window)).agg({ 'val': ['std', 'mean'] })

执行时间下降到:

Time needed: 0.9421329498291016 seconds
Time needed: 0.9423763751983643 seconds
Time needed: 0.9420042037963867 seconds
Time needed: 0.9560058116912842 seconds
Time needed: 0.9728689193725586 seconds

我还尝试将自定义函数简化为:

def coeff_of_var(series):
    return 1

在本例中执行时间为:

Time needed: 32.465901136398315 seconds
Time needed: 34.14194059371948 seconds
Time needed: 38.883220195770264 seconds
Time needed: 44.430686950683594 seconds
Time needed: 42.99840021133423 seconds

您知道自定义函数速度缓慢的原因是什么吗?


编辑

您可以使用以下代码重现该问题:

import numpy as np
import pandas as pd

import time

def coeff_of_var(series):
    return 1 #series.std() / series.mean()

nrows = 3070584
ntrue = 450000
window = 5

rng = pd.date_range('2015-01-01 00:00:00', periods=nrows, freq='min')
data = pd.DataFrame({ 'A': rng, 'B' : np.random.randn(len(rng)), 'C' : np.random.randn(len(rng)), 'D' : np.random.randn(len(rng)), 'E' : np.zeros(len(rng), dtype=bool)})

data.loc[np.random.choice(np.arange(nrows), ntrue, replace=False), 'E'] = True

start_time = time.time()

channel_data = data[data['E'] == True].sort_values('A')
channel_data['A'] = pd.to_datetime(channel_data['A'],format='%Y-%m-%d %H:%M:%S').dt.floor('d')
channel_data = channel_data.set_index('A')

rolling_data = channel_data.rolling('{}D'.format(window)).agg({ 'B': coeff_of_var })

rolling_data = rolling_data.groupby(rolling_data.index.floor('d')).last()[window:]

print('Time needed: {} seconds'.format(time.time() - start_time))

最佳答案

我运行你的代码得到了类似的结果,所以我用谷歌搜索了一下。不幸的是,我发现的内容非常模糊,但我认为分享它可能仍然会给您一些想法:

Optimize Custom Grouping Function

TL;博士:

Pandas cannot optimize custom functions. It has a limited number of builtin grouping methods. All of these are optimized and should yield better performance.

虽然我知道这不是一个令人满意的答案,但我希望它仍然会有一些帮助。

关于python - pandas 聚合中的自定义函数非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56289758/

相关文章:

python - 在 Python 中获取计时器刻度

python - 计算 Pandas 的牛市/熊市

python - 使用 pandas.to_csv 时如何指定日期格式?

python - 将一列中的文本拆分为三列

python - 内部服务器错误 : Dash on Flask on AWS Elastic Beanstalk

Python,调用以数字开头的 pandas 系列

javascript - 代码的技术名称不属于任何功能

python - 如何为不同的分类列创建带有编码的管道?

python - Pandas 日期时间格式不起作用 - python

python - 如何在 easy_install 中更改站点包目录的路径