问题定义:
对于一个 Pandas DataFrame,我想要获得一个按日期时间索引分组的滚动平均值,并且每行都可以指定可变窗口大小。
示例:
对于下面这个周数据的 df
:
| week_start_date | material | location | quantity | window_size |
|-----------------|----------|----------|----------|-------------|
| 2019-01-28 | C | A | 870 | 1 |
| 2019-02-04 | C | A | 920 | 3 |
| 2019-02-18 | C | A | 120 | 1 |
| 2019-02-25 | C | A | 120 | 2 |
| 2019-03-04 | C | A | 120 | 1 |
| 2018-12-31 | D | A | 1200 | 8 |
| 2019-01-21 | D | A | 720 | 8 |
| 2019-01-28 | D | A | 480 | 8 |
| 2019-02-04 | D | A | 600 | 8 |
| 2019-02-11 | D | A | 720 | 8 |
| 2019-02-18 | D | A | 80 | 8 |
| 2019-02-25 | D | A | 600 | 8 |
| 2019-03-04 | D | A | 1200 | 8 |
| 2019-01-14 | E | B | 150 | 1 |
| 2019-01-28 | E | B | 1416 | 1 |
| 2019-02-04 | F | B | 1164 | 1 |
| 2019-01-28 | G | B | 11520 | 8 |
窗口需要相对于
week_start_date
中设置的实际日期,而不是将其视为整数索引。它需要按
material
和 location
进行分组。滚动平均值适用于列
quantity
。窗口大小需要根据
window_size
列中的值变化/更改。此值随时间变化 - 它表示需要聚合数量的过去几周的数量。当行不可用时,平均值应假定该值为 0,即:
当一个以星期为单位的行不可用时
mean(null, null, null, 1000) = 1000
但实际上应该是:
mean(0,0,0,1000)=250
然而 - 这仅适用于第一次观测之后。
固定窗口,相对于日期列:
我可以使用以下内容获得 8 周(56 天)的静态窗口:df.set_index('week_start_date').groupby(['material', 'location'])['quantity'].rolling('56D', min_periods=1).mean()
我已经尝试过使用expanding,但没有成功。
如何将窗口大小设置相对于它读取的每一行?
样本数据:
Original Answer翻译成"最初的回答"
# Example Data
df = pd.DataFrame({'week_start_date': ['2019-01-28','2019-02-04','2019-02-18','2019-02-25','2019-03-04','2018-12-31','2019-01-21','2019-01-28','2019-02-04','2019-02-11','2019-02-18','2019-02-25','2019-03-04','2019-01-14','2019-01-28','2019-02-04','2019-01-28'],
'material': ['C','C','C','C','C','D','D','D','D','D','D','D','D','E','E','F','G'],
'location': ['A','A','A','A','A','A','A','A','A','A','A','A','A','B','B','B','B'],
'quantity': ['870','920','120','120','120','1200','720','480','600','720','80','600','1200','150','1416','1164','11520'],
'min_of_pdt_or_8_weeks': ['1','3','1','2','1','8','8','8','8','8','8','8','8','1','3','1','8']})
# Fix formats
df['week_start_date'] = pd.to_datetime(df['week_start_date'])
df['actual_week_qty'] = df['quantity'].astype(float)
期望的结果:
| material | location | week_start_date | quantity |
| C | A | 2019-01-28 | 870 |
| C | A | 2019-04-02 | 306.6667 |
| C | A | 2019-02-18 | 520 |
| C | A | 2019-02-25 | 386.6667 |
| D | A | 2018-12-31 | 1200 |
| D | A | 2019-01-21 | 960 |
| D | A | 2019-01-28 | 800 |
| D | A | 2019-04-02 | 600 |
| D | A | 2019-11-02 | 720 |
| D | A | 2019-02-18 | 400 |
| D | A | 2019-02-25 | 466.6667 |
| D | A | 2019-04-03 | 650 |
| E | B | 2019-01-14 | 150 |
| E | B | 2019-01-28 | 783 |
| F | B | 2019-04-02 | 1164 |
| G | B | 2019-01-28 | 11520 |
mean(null, null, null, 1000) = 1000
但实际上应该是: mean(0,0,0,1000)=250 然而 - 这仅适用于第一个观测已被测量之后,以避免新条目对其前N个条目具有错误值。是的,它的潜在选项被硬性限制为8个。 - undefined