如何对DataFrame中YoY超出阈值的'tot_dl_vol'列值进行盖帽处理?
对DataFrame同比(YoY)异常值进行盖帽处理
需求说明
我有一个包含tot_dl_vol列的DataFrame,需要对该列中**同比增长超过80%或同比下降超过10%**的值做盖帽处理——把超出阈值的数值替换为基于去年同期值计算的阈值上限/下限。
已实现代码
df['YoY_dl'] = (df['tot_dl_vol'].pct_change(12)) * 100 upper = 80 lower = 10 df.loc[df['YoY_dl'] > upper, 'tot_dl_vol'] = df['tot_dl_vol'].shift(12) * (1 + upper/100) df.loc[df['YoY_dl'] < lower, 'tot_dl_vol'] = df['tot_dl_vol'].shift(12) * (1 - lower/100)
示例DataFrame
数据构造代码
import pandas as pd from pandas import Timestamp data = {'key': ['A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A1'], 'volume': [1714.11, 1907.1, 2927.58, 2656.2, 2364.18, 2372.41, 2363.76, 1956.16, 4146.98, 1971.72, 2588.72, 1853.93, 2050.91, 2267.84, 2634.94, 2750.46, 3072.91, 3363.62, 2717.2, 2273.96, 2228.8, 1886.77, 1864.19], 'ds': [Timestamp('2021-04-01 00:00:00'), Timestamp('2021-05-01 00:00:00'), Timestamp('2021-06-01 00:00:00'), Timestamp('2021-07-01 00:00:00'), Timestamp('2021-08-01 00:00:00'), Timestamp('2021-09-01 00:00:00'), Timestamp('2021-10-01 00:00:00'), Timestamp('2021-11-01 00:00:00'), Timestamp('2021-12-01 00:00:00'), Timestamp('2022-01-01 00:00:00'), Timestamp('2022-02-01 00:00:00'), Timestamp('2022-03-01 00:00:00'), Timestamp('2022-04-01 00:00:00'), Timestamp('2022-05-01 00:00:00'), Timestamp('2022-06-01 00:00:00'), Timestamp('2022-07-01 00:00:00'), Timestamp('2022-08-01 00:00:00'), Timestamp('2022-09-01 00:00:00'), Timestamp('2022-10-01 00:00:00'), Timestamp('2022-11-01 00:00:00'), Timestamp('2022-12-01 00:00:00'), Timestamp('2023-01-01 00:00:00'), Timestamp('2023-02-01 00:00:00')]} df = pd.DataFrame(data)
数据预览
| key | volume | ds |
|---|---|---|
| A1 | 1714.11 | 2021-04-01 00:00:00 |
| A1 | 1907.10 | 2021-05-01 00:00:00 |
| A1 | 2927.58 | 2021-06-01 00:00:00 |
| A1 | 2656.20 | 2021-07-01 00:00:00 |
| A1 | 2364.18 | 2021-08-01 00:00:00 |
| A1 | 2372.41 | 2021-09-01 00:00:00 |
| A1 | 2363.76 | 2021-10-01 00:00:00 |
| A1 | 1956.16 | 2021-11-01 00:00:00 |
| A1 | 4146.98 | 2021-12-01 00:00:00 |
| A1 | 1971.72 | 2022-01-01 00:00:00 |
| A1 | 2588.72 | 2022-02-01 00:00:00 |
| A1 | 1853.93 | 2022-03-01 00:00:00 |
| A1 | 2050.91 | 2022-04-01 00:00:00 |
| A1 | 2267.84 | 2022-05-01 00:00:00 |
| A1 | 2634.94 | 2022-06-01 00:00:00 |
| A1 | 2750.46 | 2022-07-01 00:00:00 |
| A1 | 3072.91 | 2022-08-01 00:00:00 |
| A1 | 3363.62 | 2022-09-01 00:00:00 |
| A1 | 2717.20 | 2022-10-01 00:00:00 |
| A1 | 2273.96 | 2022-11-01 00:00:00 |
| A1 | 2228.80 | 2022-12-01 00:00:00 |
| A1 | 1886.77 | 2023-01-01 00:00:00 |
| A1 | 1864.19 | 2023-02-01 00:00:00 |
代码说明与注意事项
- 同比计算逻辑:用
pct_change(12)计算12期(月度数据的同比)变化率,转成百分比的逻辑没问题。 - 盖帽规则:
- 同比增长超80%时,替换为去年同期值×1.8
- 同比下降超10%时,替换为去年同期值×0.9
- 实操提醒:
- 如果数据有多分组(比如示例里的
key列),要先按分组处理,用df.groupby('key').apply(...)避免跨组计算错误 - 处理前必须确保数据按时间排序,否则
shift(12)和pct_change(12)会出错
- 如果数据有多分组(比如示例里的
内容的提问来源于stack exchange,提问作者sherin_a27
相关产品推荐
相关产品推荐

