首页 > 解决方案 > 如何在不使用循环或在 Pandas 中迭代(groupby)组的情况下应用可迭代窗口的滚动功能?

问题描述

这个问题实际上是前一个问题的“衍生”

但是这一次,想象一下你有这个“DataFrame”,但要大得多

      DATE  ITEM   STORE   LT  SALES
2018-06-06     A    L001    4      3
2018-06-06     A    L002    2      1
2018-06-06     A    L003    3      3
2018-06-06     B    L001    4      1
2018-06-06     B    L002    2      0

我添加了代表“交货时间”的列“LT”,并将库存切换为“销售”。这只是“DataFrame”的头部。您可以使用以下代码重现相同的内容:

import pandas as pd
import numpy as np
import itertools as it

lojas = ['L001', 'L002', 'L003']
itens = list("ABC")
lead_times = {'L001':4,'L002':2,'L003':3}
dr = pd.date_range(start='2018-06-06', end='2018-06-12')

df = pd.DataFrame(data=list(it.product(dr, itens, lojas)), columns=['DATE', 'ITEM', 'STORE'])
df['LT'] = df.STORE.map(lead_times)
df['SALES'] = np.random.RandomState(seed=101).randint(0,5, size=len(df.ITEM))

如果您阅读该主题,您会看到用户 @coldspeed 提供了以下答案来计算天之间的位置 STOCK 差异:

v = df.groupby(['ITEM', 'STORE'], sort=False).STOCK.diff()
df['DELTA'] = np.where(np.isnan(v), 0, v)

现在想象一下,我们现在想要的是计算每个 STORE 中销售额的滚动和(前向),但窗口参数取决于 LT 列。产生下面的结果(我将把头部和尾部附加在一起,这样你就可以看到 2 个例子):

      DATE  ITEM    STORE   LT  SALES   ACC_SALES
2018-06-06     A     L001    4      3         7.0
2018-06-07     A     L001    4      0        11.0
2018-06-08     A     L001    4      3        11.0
2018-06-09     A     L001    4      0         NaN
2018-06-10     A     L001    4      4         NaN
2018-06-11     A     L001    4      4         NaN
2018-06-12     A     L001    4      3         NaN
...
2018-06-06     C     L003    3      4         8.0
2018-06-07     C     L003    3      3         7.0
2018-06-08     C     L003    3      3         8.0
2018-06-09     C     L003    3      2         6.0
2018-06-10     C     L003    3      2         NaN
2018-06-11     C     L003    3      4         NaN
2018-06-12     C     L003    3      0         NaN

[编辑] 有我用来计算“ ACC_SALES ”的代码:

grouped_df = df.groupby(['ITEM','STORE'])
auxlist = []

for (name, group) in grouped_df:
    aux = group.copy()
    aux.sort_values('DATE', inplace=True)
    aux.reset_index(drop=True, inplace=True)
    win = lead_times[aux.STORE.iloc[0]]
    aux['ACC_SALES'] = aux.SALES.rolling(window=win, min_periods=1).sum().shift(-1*win)
    auxlist.append(aux)

df = pd.concat(auxdf)

有没有一种快速、矢量化的“numpythonic”方法来获得这个结果而无需迭代组?

标签: pythonpandasnumpy

解决方案


推荐阅读