7-2 resample重采样复诊


文档摘要

7-2 resample:按频率复诊 本节摘要:resample按新频率把时间索引重新分组——降采样把高频压成低频(日到月),升采样把低频铺成高频(月到日)。本节核心:聚合口径决定指标含义,月的sum是总额、月的mean是日均水平,两者是完全不同的诊断结论。 随访档案建好(7-1),复诊开始。日销售额三千行没人看,管理层要月报。把日粒度重新编排成月粒度,就是重采样的降采样。 降采样:日到月 sum与mean的差距就是口径的差距:总额看规模,日均看水平。一月31天总额最高,可能只是因为天数多——只看总额会被日历骗,只看日均会被大单骗,会诊报告两个都要。这本质上是5-1的GroupBy套了一层时间频率外衣,agg的四种输出形态在这里同样适用。

7-2 resample:按频率复诊

本节摘要:resample按新频率把时间索引重新分组——降采样把高频压成低频(日到月),升采样把低频铺成高频(月到日)。本节核心:聚合口径决定指标含义,月的sum是总额、月的mean是日均水平,两者是完全不同的诊断结论。

随访档案建好(7-1),复诊开始。日销售额三千行没人看,管理层要月报。把日粒度重新编排成月粒度,就是重采样的降采样。

降采样:日到月

import pandas as pd idx = pd.date_range('2024-01-01', periods=90, freq='D') daily = pd.Series(range(1000, 1000 + 90 * 10, 10), index=idx) # 降采样到月:sum口径 = 月总额 monthly_sum = daily.resample('MS').sum() print(monthly_sum) # 2024-01-01 70350 # 2024-02-01 118860 # 2024-03-01 52200 # Freq: MS, Name: ..., dtype: int64 # mean口径 = 月内日均 monthly_mean = daily.resample('MS').mean() print(monthly_mean.round(1)) # 2024-01-01 1205.0 # 2024-02-01 1440.0 # 2024-03-01 1740.0

sum与mean的差距就是口径的差距:总额看规模,日均看水平。一月31天总额最高,可能只是因为天数多——只看总额会被日历骗,只看日均会被大单骗,会诊报告两个都要。这本质上是5-1的GroupBy套了一层时间频率外衣,agg的四种输出形态在这里同样适用。

常用频率速查

频率串 含义 频率串 含义
D 日历日 B 工作日
W 周末收于周日 MS 月初
M 月末 QS / Q 季初 / 季末
H 小时 min 分钟

MS与M的区别要留心:MS标在月初(1月1日),M标在月末(1月31日)。月报标签想对齐月初就MS,与财务对账用M。

升采样:铺格子与填格子

# 季度数据铺成月度格子 quarterly = pd.Series([3000, 3600], index=pd.to_datetime(['2024-01-01', '2024-04-01'])) monthly_grid = quarterly.resample('MS').asfreq() print(monthly_grid) # 2024-01-01 3000.0 # 2024-02-01 NaN ← 铺出来的空格子 # 2024-03-01 NaN # 2024-04-01 3600.0 # 三种填法:前值填充、插值、置零 print(monthly_grid.ffill().head(3)) # 2024-01-01 3000.0 # 2024-02-01 3000.0 ← 沿用上季 # 2024-03-01 3000.0 print(monthly_grid.interpolate().head(3)) # 2024-01-01 3000.0 # 2024-02-01 3200.0 ← 线性爬坡 # 2024-03-01 3400.0

升采样制造缺失,填法的选择就是3-1补值策略的时间版:存量指标(库存、费率)用ffill,流量指标(销售额、访问量)绝不ffill——上季的销售额不能算到二头上,流量插值或干脆保持NaN。

⚠️ 常见坑:流量类数据升采样后ffill,等于把季度总额复制成三个月的"月总额",年报一汇总变四倍。判断标准就一条:这个指标是存量还是流量

OHLC与多列复诊

# 财经式复诊:开高低收 print(daily.resample('MS').ohlc()['open']) # 2024-01-01 1000 # 2024-02-01 1310 # 2024-03-01 1590 # 多列表的复诊:金额求和、门店数取均值——agg字典口径 df = pd.DataFrame({ '金额': daily.values, '笔数': [i % 5 + 1 for i in range(90)], }, index=idx) report = df.resample('MS').agg({'金额': 'sum', '笔数': 'mean'}) print(report.round(1)) # 金额 笔数 # 2024-01-01 70350 3.0 # 2024-02-01 118860 3.0 # 2024-03-01 52200 3.1

复诊的口径选择

降采样与升采样的处置路径

降采样与升采样的处置路径

本节要点回顾

  • resample是按频率的分组,GroupBy的一切知识平移适用
  • 口径即含义:sum看规模、mean看水平,报告建议双指标
  • MS与M的标签差异:月报对齐月初、财务对账用月末
  • 升采样先asfreq造格再填,存量ffill、流量不ffill
  • agg字典让不同列各用各的口径

追问:resample和groupby按月份分有什么不一样

时间索引既能resample('MS')也能groupby(index.month),结果看起来都是月度数,差在哪?三处:resample的输出仍是时间索引(可以继续rolling、可以按时间切片),groupby月份输出的是普通分类索引;resample跨年自然区分(2023年1月与2024年1月是两期),groupby月份会把两年的一月并到一组,跨年数据直接踩坑;resample的频率体系(MS、W、Q)开箱即用,groupby要自己拼。经验法则:数据有时间索引就用resample,按非时间维度分组才用groupby,两者还能嵌套(每月内再按门店分组),那已是报表管线的标准姿势。

# 跨年陷阱演示:groupby月份合并了两年的一月 two_years = pd.Series([10, 20], index=pd.to_datetime(['2023-01-05', '2024-01-05'])) print(two_years.groupby(two_years.index.month).sum()) # 1 30 ← 两年的一月被并成一组 print(two_years.resample('MS').sum()) # 2023-01-01 10 # 2024-01-01 20 ← resample分得清年份

下一节给复诊数据配上持续监护:rolling移动窗口。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U