首页 > 解决方案 > 提高应用方法的性能

问题描述

我想按我的df“cod_id”的变量分组,然后应用这个函数:

[df.loc[df['dt_op'].between(d, d + pd.Timedelta(days = 7)), 'quantity'].sum() \
                        for d in df['dt_op']]

从这个df移动:

print(df)
dt_op      quantity      cod_id
20/01/18      1            613
21/01/18      8            611
21/01/18      1            613 
...

对此:

print(final_df)
n = 7

dt_op      quantity   product_code     Final_Quantity
20/01/18      1            613               2
21/01/18      8            611               8
25/01/18      1            613               1
...

我试过:

def lookforward(x):
    L = [x.loc[x['dt_op'].between(row.dt_op, row.dt_op + pd.Timedelta(days=7)), \
         'quantity'].sum() for row in x.itertuples(index=False)]
    return pd.Series(L, index=x.index)

s = df.groupby('cod_id').apply(lookforward)
s.index = s.index.droplevel(0)

df['Final_Quantity'] = s

print(df)

       dt_op  quantity  cod_id  Final_Quantity
0 2018-01-20         1     613               2
1 2018-01-21         8     611               8
2 2018-01-21         1     613               1

但这不是一个有效的解决方案,因为它的计算速度很慢

我怎样才能提高 它的性能?即使使用导致相同结果的新代码/新功能,我也会实现它。

编辑:

原始数据集的子集,只有一个产品(cod_id == 2),我尝试在“wm”提供的代码上运行:

   print(df)

    cod_id  dt_op          quantita  final_sum
0        2 2017-01-03         1       54.0
1        2 2017-01-04         1       53.0
2        2 2017-01-13         1       52.0
3        2 2017-01-23         2       51.0
4        2 2017-01-26         1       49.0
5        2 2017-02-03         1       48.0
6        2 2017-02-27         1       47.0
7        2 2017-03-05         1       46.0
8        2 2017-03-15         1       45.0
9        2 2017-03-23         1       44.0
10       2 2017-03-27         2       43.0
11       2 2017-03-31         3       41.0
12       2 2017-04-04         1       38.0
13       2 2017-04-05         1       37.0
14       2 2017-04-15         2       36.0
15       2 2017-04-27         2       34.0
16       2 2017-04-30         1       32.0
17       2 2017-05-16         1       31.0
18       2 2017-05-18         1       30.0
19       2 2017-05-19         1       29.0
20       2 2017-06-03         1       28.0
21       2 2017-06-04         1       27.0
22       2 2017-06-07         1       26.0
23       2 2017-06-13         2       25.0
24       2 2017-06-14         1       23.0
25       2 2017-06-20         1       22.0
26       2 2017-06-22         2       21.0
27       2 2017-06-28         1       19.0
28       2 2017-06-30         1       18.0
29       2 2017-07-03         1       17.0
30       2 2017-07-06         2       16.0
31       2 2017-07-07         1       14.0
32       2 2017-07-13         1       13.0
33       2 2017-07-20         1       12.0
34       2 2017-07-28         1       11.0
35       2 2017-08-06         1       10.0
36       2 2017-08-07         1        9.0
37       2 2017-08-24         1        8.0
38       2 2017-09-06         1        7.0
39       2 2017-09-16         2        6.0
40       2 2017-09-20         1        4.0
41       2 2017-10-07         1        3.0
42       2 2017-11-04         1        2.0
43       2 2017-12-07         1        1.0

标签: pythonpandasperformanceapplypandas-groupby

解决方案


编辑 181017:由于 pandas目前不支持稀疏时间序列上的前向滚动功能,此方法不起作用,请参阅评论。

在执行 pandas 操作时,使用 for 循环可能会成为性能杀手。

围绕行的 for 循环加上 7 天的 timedelta 可以替换为.rolling("7D"). 为了获得前滚时间增量(当前日期 + 7 天),我们反转df按日期,如下所示

然后不再需要自定义函数,您可以.quantity.sum()从 groupby 中获取。

quant_sum = df.sort_values("dt_op", ascending=False).groupby("cod_id") \
              .rolling("7D", on="dt_op").quantity.sum()

cod_id  dt_op     
611     2018-01-21    8.0
613     2018-01-21    1.0
        2018-01-20    2.0
Name: quantity, dtype: float64

result = df.set_index(["cod_id", "dt_op"])
result["final_sum"] = quant_sum
result.reset_index()

   cod_id      dt_op  quantity  final_sum
0     613 2018-01-20         1        2.0
1     611 2018-01-21         8        8.0
2     613 2018-01-21         1        1.0

推荐阅读