python - 如何提高 python 数据帧中平均计算的性能

标签 python python-3.x pandas

我正在尝试提高当前代码段的性能,由此循环遍历一个数据帧(数据帧“r”)并根据条件从另一个数据帧(数据帧“p”)中找到平均值。

我想从数据帧“p”中找到所有值(“Val”列)的平均值,其中 (r.RefDate = p.RefDate) & (r.Item = p.Item) & (p.StartDate >= r.StartDate) & (p.EndDate <= r.EndDate)

可以按照以下方式生成此虚拟数据;

import pandas as pd
import numpy as np
from datetime import datetime


######### START CREATION OF DUMMY DATA ##########

rng = pd.date_range('2019-01-01', '2019-10-28')
daily_range = pd.date_range('2019-01-01','2019-12-31')

p = pd.DataFrame(columns=['RefDate','Item','StartDate','EndDate','Val'])
for item in ['A','B','C','D']:
    for date in daily_range:
        daily_p = pd.DataFrame({ 'RefDate': rng,
                            'Item':item, 
                            'StartDate':date,
                            'EndDate':date,
                            'Val' : np.random.randint(0,100,len(rng))}) 
        p = p.append(daily_p)


r = pd.DataFrame(columns=['RefDate','Item','PeriodStartDate','PeriodEndDate','AvgVal'])
for item in ['A','B','C','D']:
    r1 = pd.DataFrame({ 'RefDate': rng,
                        'Item':item, 
                        'PeriodStartDate':'2019-10-25',
                        'PeriodEndDate':'2019-10-31',#datetime(2019,10,31),
                        'AvgVal' : 0}) 
    r = r.append(r1)
r.reset_index(drop=True,inplace=True)

######### END CREATION OF DUMMY DATA ##########

我目前正在计算并希望提高性能的一段代码如下

for i in r.index:

    avg_price = p['Val'].loc[((p['StartDate'] >= r.loc[i]['PeriodStartDate']) & 
                         (p['EndDate'] <= r.loc[i]['PeriodEndDate']) &
                         (p['RefDate'] == r.loc[i]['RefDate']) &
                         (p['Item'] == r.loc[i]['Item']))].mean()

    r['AvgVal'].loc[i] = avg_price

最佳答案

第一个变化是生成r DataFrame,PeriodStartDatePeriodEndDate 创建为 datetime,请参阅以下片段 启动代码,由我更改:

r1 = pd.DataFrame({'RefDate': rng, 'Item':item,
    'PeriodStartDate': pd.to_datetime('2019-10-25'),
    'PeriodEndDate': pd.to_datetime('2019-10-31'), 'AvgVal': 0}) 

为了获得更快的速度,我将两个 DataFrame 中的索引设置为 RefDateItem (两列比较相等)并按索引排序:

p.set_index(['RefDate', 'Item'], inplace=True)
p.sort_index(inplace=True)
r.set_index(['RefDate', 'Item'], inplace=True)
r.sort_index(inplace=True)

这样,通过索引访问会明显更快。

然后我定义了以下函数来计算行的平均值 来自 p 来自 r 的当前行“相关”:

def myMean(row):
    pp = p.loc[row.name]
    return pp[pp.StartDate.ge(row.PeriodStartDate) &
        pp.EndDate.le(row.PeriodEndDate)].Val.mean()

唯一要做的就是应用这个函数(到 r 中的每一行)并且 将结果保存在 AvgVal 中:

r.AvgVal = r.apply(myMean2, axis=1)

使用 %timeit,我将 EdH 提出的代码的执行时间与我的进行了比较 得到的结果几乎缩短了 10 倍。

自行检查。

关于python - 如何提高 python 数据帧中平均计算的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58645436/

相关文章:

python - Django QuerySet .count() 为 0 并且 .exists() 为 false,即使 QuerySet 中有一个对象(Django Rest Framework)

python - 使用 Python 解析 XML 文件

python - 尽管格式正确, Pandas 仍无法推断时间序列频率?

python - 按其他列值汇总行 - Python/Pandas 中的 Countif

python - 如何找到具有时间戳索引的 DataFrame 中的前一行?

python - 添加多个约束到 scipy 最小化,自动生成约束字典列表?

python - python中random.sample生成的序列重复的概率是多少?

python - 通过计算传播 NaN

Python并发 future executor.submit超时

python - 在 Pandas 中,如何水平连接然后删除冗余列