【发布时间】:2019-09-09 05:35:19
【问题描述】:
问题定义:
对于 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
但实际上应该:
平均值(0,0,0,1000)=250
但是 - 这应该仅在测量第一次观察后才适用。
固定窗口,相对于日期列:
我可以使用以下方法获得 8 周(56 天)的静态窗口:
df.set_index('week_start_date').groupby(['material', 'location'])['quantity'].rolling('56D', min_periods=1).mean()
我已经探索过expanding 的使用,但没有成功。
如何相对于它读取的每一行设置窗口大小?
样本数据:
# 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 |
【问题讨论】:
-
你能显示预期的输出吗?
-
@EdekiOkoh 已将预期结果添加到帖子中。
-
为什么第二行是 920?
-
@QuangHoang 920 因为 window_size 为 3,但没有 02/04/2019 之前 3 周的数据
-
@credibly-close-mean "没有数据" 为什么不能算 0?所以等效的“慢代码”是做8个不同的计算(每个1w,2w,...,8w滚动窗口一个)然后在window_size上合并(注:window_size NaN的fillna -> 8应该先完成,它是这里有点噪音)。您的真实示例实际上是1-8吗?我有点怀疑击败 8 计算 + 连接是多么容易。另外, actual_week_qty col 是否与数量相同?我有一个解决方案......虽然我认为这是愚蠢的英文日期格式的一个小问题(请使用规范的 iso 格式!)
标签: python pandas pandas-groupby