新闻详情

新闻详情

首页 / 资讯中心 / 详情

pandas resample重采样完全指南:从参数到实战避坑

发布时间:2026/9/30 8:33:31来源:尧图网络
pandas resample重采样完全指南:从参数到实战避坑
简介针对 Pandas 时间序列处理中的 resample 重采样方法这份资料系统梳理了从高频到低频的降采样、从低频到高频的升采样两大核心场景。内容逐一解析 freq、how、axis、fill_method、closed、label、loffset、limit、kind、convention 等关键参数并结合分钟级 Series 实例演示 sum、asfreq、pad、bfill 以及自定义 apply 的典型用法帮助数据分析、金融量化、物联网等领域的学习者快速掌握数据频率转换与聚合技巧。资料还涉及时间桶边界控制、标签设置与缺失值填充等实操细节适合有一定 Pandas 基础、希望深入理解重采样机制的读者。资源以 PDF 格式提供共 1 个文件压缩包仅 44KB轻量便携。目前已有 1850 人学习对于想系统理解 resample 参数细节和阅读代码示例的用户具有较好的参考价值。1. 做行情聚合和数据清洗的人迟早会撞上 pandas resample 重采样手里是五分钟一条的行情数据老板要你出日线、出周线传感器每 10 秒上报一次温度要按小时聚合算均值日志表里一堆时间戳要按天统计请求量。新手第一反应是把时间戳截断成日期再用 groupby老手会直接说用 pandas 的 resample。resample 是 pandas 库里专门针对时间序列做重采样的工具它做的事很简单把时间轴按规则切块再在每个块里做聚合或者填充对应降采样和升采样两条路线。这篇文章按「先搞懂参数、再降采样落地、再升采样处理、最后集中排坑」的顺序讲适合已经会 pandas 基本操作、但还没系统用过时间序列功能的人。2. 四个必调参数rule、closed、label、offset 怎么配合2.1 rule 参数频率字符串才是重采样的核心resample 的第一个参数是 rule它决定按什么粒度切时间轴。rule 可以是一个频率字符串也可以是 pandas 的 DateOffset 对象。字符串的规则和 date_range 完全一致D 表示自然日、B 表示工作日、H 表示小时、T 或 min 表示分钟、S 表示秒、W 表示周、M 表示日历月末、Q 表示季度末、A 表示年末。基础字母前加数字就是倍数比如15min、2H、3D这是最日常的写法。import pandas as pd import numpy as np rng pd.date_range(2024-01-02 09:31, periods30, freq5min) df pd.DataFrame( { price: np.cumsum(np.random.randn(30)) 100, volume: np.random.randint(100, 500, 30), }, indexrng, ) # 按 30 分钟切块桶左边界作为标签桶内价格取最后一笔、成交量求和 bar30 df.resample(30min).agg({price: last, volume: sum}) print(bar30.head())rule 写成30min之后pandas 从时间轴的起点按 30 分钟一格切出桶边界。上面的 agg 字典里price 用last取桶内最后一笔成交价volume 用sum加总桶内成交量。这里最常见的错误是直接df.resample(30min).sum()那样 price 也会被求和明显不符合 K 线的语义。所以 agg 字典是重采样最常用的写法后面几章都按这个来。B 和 M 这两个频率要特别留意。resample(B)会把周末直接排除一天一根的日线序列里不会出现周六周日resample(M)的锚点是日历月末桶的标签是月末日期。如果拿日内数据直接按 M 切第一根桶只包含当月最后那一段行情这个行为不是 bug是频率本身的定义。拿不准的时候可以把结果打印出来看索引而不是猜。rule 参数还接受 DateOffset 对象。pd.offsets.Minute(30)等价于30minpd.offsets.Week(weekday3)类似W-THU。字符串能表达绝大部分频率但节假日这种不规则偏移只有 DateOffset 能表达这个放到最后一章展开。2.2 closed 与 label桶边界决定数据归属标签只改名字closed 和 label 是 resample 里最容易被混着调的两个参数。closed 决定每个桶包含哪些点label 只决定桶的标签取左边界还是右边界。它们是两件事但很多人以为改 label 就能改聚合结果实际上改的是索引显示。# 左闭右开09:30 到 10:00 之间的数据归到 09:30 这个桶 bar_left df.resample(30min, closedleft, labelleft).agg({price: last, volume: sum}) # 右闭左开09:30 到 10:00 之间的数据归到 10:00 这个桶 bar_right df.resample(30min, closedright, labelright).agg({price: last, volume: sum}) print(bar_left.head(2)) print(bar_right.head(2))用 09:31 开始的数据closedleft时第一根桶是[09:30, 10:00)包含 09:31 到 09:56 六根五分钟线closedright时桶变成(09:30, 10:00]这六根数据仍然归同一个桶但标签从 09:30 变成 10:00。如果数据里恰好有踩在 09:30:00 这个点上的记录两种 closed 对这个点的归属会给出完全不同的结果这正是后面避坑章节的源头。实际使用中M、Q、A 这类日历频率的默认 closed 是 right也就是桶是「上个边界到这个边界」的右闭区间D 和 H 频率默认是 left。别依赖默认值显式写 closed 和 label同一套代码在不同 pandas 版本之间跑出来的结果才一致。提示closed 决定数据归到哪个桶label 只改这个桶叫什么名字。两个参数不要混着调否则会出现「数据归到 09:25 桶、标签写 09:30」这种错位。2.3 offset 与 origin把锚点从 0 点挪到业务开盘时间resample 的桶边界默认锚定在时间轴的 0 点。对股票、期货这类有开盘时间的业务0 点锚会带来一个很尴尬的后果9:30 开盘的数据会被切进[0:00, 次日 0:00)这种桶里日线只有早上那一段看起来像数据缺了大半。offset 就是干这个用的。# 把日线桶的起点从 0 点平移到 9:30 bar_day df.resample(D, offsetpd.Timedelta(9 hours 30 minutes)).agg( {price: last, volume: sum} ) print(bar_day) # 或者让第一个桶从第一条数据开始切 bar_day2 df.resample(D, originstart).agg({price: last, volume: sum}) print(bar_day2)offset 把桶边界整体平移。默认时 D 频率的桶是[0:00, 次日 0:00)09:31 的数据孤零零待在当天的桶里offset9h30min之后桶变成[09:30, 次日 09:30)开盘数据就和自然交易时段对齐了。origin 参数在 pandas 1.1 之后提供originstart表示第一个桶从第一条数据开始切适合回测场景里不想让桶边界受自然日影响的情况。origin 和 offset 不能同时设置两个只能选一个。需要注意offset 不会改变数据进哪个桶的规则它只是平移桶边界。改 offset 之后同一条数据从某个桶挪到相邻桶是正常的。这一点很多人想不通以为是 bug其实再往下一章看就明白了。3. 降采样落地把分钟数据聚合成日线 VWAP3.1 先给时间列做一次数据清洗实际拿到手的数据时间列经常是从 Excel 或 CSV 读进来的字符串索引还是数字。resample 只认时间索引所以第一步永远是清洗时间列这一步做不好后面全是白搭。raw pd.read_csv(tick_sample.csv) # 假设列是 time, price, volume raw[time] pd.to_datetime( raw[time], format%Y-%m-%d %H:%M:%S, errorscoerce ) raw.dropna(subset[time], inplaceTrue) df raw.set_index(time).sort_index()to_datetime的 format 一定写上。不写 format 时 pandas 会逐条猜测格式数据量一大就慢得离谱而且混合格式时猜错的概率很高。errorscoerce把解析不了的脏值变成 NaT再统一 dropna 掉。set_index之后必须sort_index乱序时间索引在 resample 时不会直接报错但桶内数据的先后顺序可能错聚合出来的 open、first 这类值就不对。3.2 agg 组合、OHLC 与 VWAP 一起算VWAP成交量加权均价是期货和股票场景里最常用的指标之一。它不等于价格的均值而是成交额之和除以成交量之和。最稳的做法是先把price * volume算成一列再在桶内聚合后相除。# 先算成交额再按时段聚合 df[amt] df[price] * df[volume] bar30 df.resample(30min, closedleft, labelleft).agg( {price: last, volume: sum, amt: sum} ) bar30[vwap] bar30[amt] / bar30[volume] bar30.drop(columnsamt, inplaceTrue) print(bar30.head())这里 price 取lastvolume 和 amt 都取sum最后一步用两列相除得到 VWAP。有人喜欢写resample(...).apply(lambda x: np.average(x[price], weightsx[volume]))这种写法在 pandas 2.x 里能跑但遇到空桶或者列名不一致时很容易翻车。先乘后加是最朴素也最不容易出错的方式数据量大的时候速度也更快。K 线还需要开高低收直接用 ohlc 方法ohlc df[price].resample(30min, closedleft, labelleft).ohlc() print(ohlc.head())ohlc()一次性给出 open、high、low、close 四列是 K 线数据的标准输出。注意这个方法挂在 Series 上才有DataFrame 对象没有ohlc()方法。如果你手里是多列 DataFrame先选出一列价格再调用。3.3 按周、月、季度重采样日历频率的对齐细节日线做完之后下一步往往就是周线、月线、季线。日历频率的坑在于字符串里的锚点和你以为的周期可能不是一回事。weekly df.resample(W-MON, closedleft, labelleft).agg( {price: last, volume: sum} ) monthly df.resample(M, closedright, labelright).agg( {price: last, volume: sum} ) quarterly df.resample(Q, closedright, labelright).agg( {price: last, volume: sum} )W-MON表示桶边界对齐到周一做出来的周线每个桶从周一开始适合业务上「自然周」的定义。M是日历月末BM是工作日月末Q是季度末QS是季度初。M 和 Q 的默认 closed 是 right跟 D 和 H 不一样所以我在这里都显式写出来。M和MS的区别最容易搞混。M是把数据聚合到以月末为边界的桶标签是月末MS才是从月初开始切。对日内数据做月线时M的第一根桶可能只有月末最后一天的行情如果没意识到这一点看到第一根月线量特别小就会怀疑数据坏了。做特征工程时另一个常见套路是重采样之后接 ewm。比如日线降采样完对收盘价做指数加权平均生成平滑曲线ewm的参数span、adjust在不同 pandas 版本里的默认行为有差异用之前先打印一列对比一下再往下送。4. 升采样是另一条路asfreq、填充与插值4.1 asfreq 与 resample 的关系先对齐网格再决定空位怎么办升采样是把低频数据变高频比如日线补成小时线。原始数据只有一个点高频网格上其它位置都是空的所以升采样本质上只有两件事对齐网格、填空。resample 本身只建好空桶不填值真正填值要靠后面的方法。daily pd.DataFrame( {close: [10.0, 11.0, 12.0, 13.0]}, indexpd.date_range(2024-01-01, periods4, freqD), ) # asfreq 只对齐网格不填值结果全是 NaN print(daily.resample(H).asfreq().head(26)) # ffill 用前一个非空值向后填充 print(daily.resample(H).ffill().head(26))asfreq()是「只对齐、不填充」的升采样返回的序列里全是 NaN。它最大的用途是检查数据完整性看看某一天到底缺了哪些小时。resample(H).ffill()则是把 1 月 1 日的收盘价 10 一直带到 1 月 2 日 0 点中间所有小时都是 10。升采样时resample(H).last()和asfreq()在大多数情况下效果相同因为没有桶内多个点可以取但语义上还是用 asfreq 表达「对齐」更清晰。4.2 ffill、bfill、nearest 在业务场景里的正确用法填充方法的选择要看业务含义不是哪个顺眼用哪个。hourly daily.resample(H) g1 hourly.ffill() g2 hourly.bfill() g3 hourly.nearest()行情快照用ffill最合理在下一个事件发生之前价格被认为维持上一个值这符合「最新报价」的业务语义。库存盘点数据用bfill更合适因为盘点动作发生后要往前回填。nearest适合缺口两侧都有值、且缺口中间的业务含义模糊时取时间更近的一侧。ffill的 limit 参数很容易算错。一天的数据升到小时ffill(limit23)刚好能把当天剩下的 23 个小时填满但如果写成limit3一天里大部分时间还是空的。limit 是按新频率的格子数算的不是按原来的天数算的这是升采样场景里最经典的翻车点。注意升采样后一定要先isna().sum()看一眼还有多少空位。缺口数量和你预期不符往往是 limit 或者频率写错了这时候继续往下传数据下游模型拿到一堆 NaN 根本不知道原因。4.3 interpolate 平滑填充什么时候可以用、什么时候别用interpolate是升采样里看着最省事的方案一行代码就能把空位填成平滑的曲线但它有明确的适用边界。smooth daily.resample(H).interpolate(methodtime) print(smooth.head(5))methodtime会按时间间隔比例插值两个相邻日线之间插出来的是一条直线上的点。温度、水位、浓度这类连续性传感器数据用这个非常合适因为物理量本身就是连续变化的。价格、成交量、事件计数这类带跳变的数据别用插值会在两根 K 线之间造出一个不存在的成交价这种假价格进了策略回测就是血泪教训。还有一点DataFrame 的interpolate默认逐列插值。如果你 resample 的对象是多列 DataFrame一定要先确认哪些列值得插哪些列应该保持 NaN。比如volume这种计数型列被插出一个带小数的成交量下游聚合时就会报警告或者更糟悄悄算出错误结果。5. 避坑排查resample 最容易翻车的五个细节这一章写的都是实际用过才能踩出来的细节。每条都按「现象 → 原因 → 解决」来讲照着排查比重新看一遍文档快得多。5.1 时间列没转成时间索引一切白干现象df.resample(D)直接报TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of RangeIndex。从 Excel 读进来的表时间列是字符串索引是 0 到 N 的数字。原因resample 只认时间类型的索引它需要在索引上切频率桶。索引不是时间类型第一步就过不去。解决先把时间列用pd.to_datetime转成 datetime64 类型再set_index。format 参数要写上errorscoerce处理脏值。从 Excel 读文件时时间列经常带毫秒或者不统一的格式用 format 明确告诉 pandas 怎么解析能少踩很多隐蔽的坑。这一步本质就是数据清洗和数据类型转换别跳过。5.2 非数值列在 agg 里悄悄消失现象df.resample(D).sum()的结果里少了几列object 类型的列不见了。原因resample 聚合默认只对数值列生效object 列直接被忽略。更隐蔽的情况是列名和函数名冲突数据里有一列叫countdf.resample(D).count()返回的是每个桶的行数而不是对count列做计数。解决用字典显式指定每一列的聚合函数列名列全宁多勿少。如果确实想把所有数值列都 sum先用select_dtypes过滤出数值列再 resample这样代码意图也清楚。5.3 closed 和 label 在升采样时不生效这不是 bug现象df.resample(H, closedleft).asfreq()和df.resample(H, closedright).asfreq()输出完全一样改了跟没改一样。原因升采样只是把低频数据对齐到更密的时间网格不存在「切桶」这一步closed 和 label 参数只在降采样时有意义。文档里写的是这两个参数只能用于降采样但代码不会因此而报错所以很多人在这里浪费半天。解决升采样直接按上一章的方式处理用 asfreq、ffill、bfill、interpolate不需要纠结 closed。如果一定要调整对齐方式用 origin 改锚点而不是动 closed。5.4 多级索引和时区索引直接翻车现象DataFrame 被set_index([symbol, time])之后调resample(D)报错信息里出现 MultiIndex 的字样或者时区 aware 的索引在 resample 之后时间标签整体偏了 8 个小时。原因resample 要求索引是单一时间索引。多级索引里它不知道该按哪一级切桶时区索引如果在 resample 时没指定 tz 参数桶边界按 0 时区切本地早上 9 点的数据会被标到前一天或者后一天。解决多级索引先用reset_index(symbol)把其它维度挪到列里保留单独时间列做索引。时区数据先tz_convert到业务时区再 resample或者在 resample 里显式传tz参数。多标的数据用groupby(symbol).resample(...)更干净这个放最后一章讲。5.5 09:30:00 的整点数据被归到 09:25 的桶现象09:30:00 那一秒的成交数据在 5min 重采样后出现在标签为 09:25 的桶里开盘第一根 K 线看起来多了一个不该有的点。原因这是 closed 和 label 搭配错位造成的。closedright时5min 的桶是(09:25, 09:30]09:30:00 正好落在右边界上属于这个桶如果此时labelleft桶标签取左边界显示为 09:25。数据本身是 09:30 的却被打上了 09:25 的标签。解决closed 和 label 要配套使用closedright配labelright或者都用 left。对行情数据推荐统一用closedright加labelright这样整点数据归到整点标签。改完配置之后先打印 head(3) 对一下索引确认边界符合业务预期再全量跑。6. 进阶自定义交易日历和分组重采样6.1 用 CustomBusinessDay 对齐真实交易日频率字符串表达不了节假日。A 股周一不开盘的日子resample(B)依然会当成工作日处理这就是节假日日历的场景。from pandas.tseries.offsets import CustomBusinessDay holidays [ 2024-01-01, 2024-02-12, 2024-02-13, 2024-04-04, 2024-05-01, 2024-06-10, 2024-09-17, 2024-10-01, ] cn_bday CustomBusinessDay(weekmaskMon Tue Fri, holidaysholidays) result df.resample(cn_bday).agg({price: last, volume: sum})CustomBusinessDay用 weekmask 指定工作日holidays 列表跳过指定日期。注意这里只是示例的节假日列表真实生产环境要维护完整的交易所日历这个列表千万别拍脑袋写。freq 字符串做不到的事情DateOffset 对象可以做到这是升到进阶环节最值得掌握的一个能力。6.2 groupby 后再 resample多标的数据统一处理手里有多个标的的行情时正确姿势是先 groupby 再 resample而不是循环里对每个标的单独处理。multi df.assign(symbol[A] * 15 [B] * 15) result ( multi.groupby(symbol) .resample(30min) .agg({price: last, volume: sum}) ) print(result.head())groupby 之后再 resample每个组都会按同一套规则切桶返回的结果是MultiIndex第一级是 symbol第二级是时间。要落库或者继续加工记得reset_index()。symbol 要放在列里而不是索引里索引里如果还有别的维度就会触发上一章说的多级索引问题。前两年做回测时我在 label 上栽过一次收盘那一刻的数据因为边界没对齐被算进了下一根 K 线整个策略信号晚了一天。那之后我养成一个习惯任何 resample 结果先打印 head(3) 对一下索引再往下游送数据。后来所有用到 resample 的管道我都先写一个最小样例把边界验证清楚再做全量。这个习惯帮我省下了很多次返工希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ScrapeGraphAI 测试基础设施全解析:从 pytest 配置到 CI/CD 的完整实战指南 2026/9/30 10:54:40

ScrapeGraphAI 测试基础设施全解析:从 pytest 配置到 CI/CD 的完整实战指南

网页爬虫人工智能AI 应用 【免费下载链接】Scrapegraph-ai Python scraper based on AI 项目地址: https://gitcode.com/GitHub_Trending/sc/Scrapegraph-ai 点击查看 免费下载 本篇技术指南以仓库根目录下的 TESTING_INFRASTRUCTURE.md 为主干,结合 py…

阅读更多 →
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南 2026/9/30 10:54:20

北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南

北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南 随着全民健身热潮的兴起,24小时自助健身房在北京等一线城市迅速普及。与传统健身房不同,自助健身房需要一套稳定、高效的软件系统来支撑会员管理、门禁控制、设备预约、计费结算…

阅读更多 →
基于Spring Boot的网上购物系统毕设:核心模块与避坑实战指南 2026/9/30 10:54:20

基于Spring Boot的网上购物系统毕设:核心模块与避坑实战指南

每年毕设开题季,网上购物系统这类Spring Boot项目几乎是计算机专业学生最常碰到的题目之一。我当年写下"基于Spring Boot的网上购物系统"这个题名时,也觉得这不就是照着一个普通商城抄一遍嘛,但真正从需求分析做到答辩,…

阅读更多 →
服务器科普指南,建议收藏 2026/9/30 10:54:20

服务器科普指南,建议收藏

阅读更多 →
Pandas数据清洗与预处理全指南:缺失值、重复值、异常值处理实战 2026/9/30 10:54:10

Pandas数据清洗与预处理全指南:缺失值、重复值、异常值处理实战

做数据相关工作的人,多少都经历过这种场面:辛辛苦苦把数据拿回来,打开一看,日期列里混着"2024/03/01""2024-3-1""20240301"三种写法;订单金额有几千个空值;同一个客户在同一…

阅读更多 →
社区康养系统开发:老人档案与上门服务预约设计 2026/9/30 10:54:10

社区康养系统开发:老人档案与上门服务预约设计

社区康养系统开发:老人档案与上门服务预约设计随着智慧社区、居家养老数字化落地,社区康养系统成为基层养老服务标准化、精细化管控的核心载体。区别于普通业务系统,康养系统具备数据合规性要求高、服务对象特殊、预约流程严谨、服务按需定制…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉