向量化校验日期列序列:DataFrame结算值批量置零的Pythonic方案
高效处理Pandas DataFrame:将年度数据不完整的Settlement置0
问题背景
现有如下结构的Pandas DataFrame:
Market Date Begin Date Settlement 0 2016-01-01 2016-01-01 26.1935 1 2016-01-01 2016-02-01 24.1071 2 2016-01-01 2016-03-01 21.0591 3 2016-01-01 2016-04-01 20.7348 4 2016-01-01 2016-05-01 20.2072 ... ... ... ... 265198 2022-09-21 2031-04-01 65.1300 265199 2022-09-21 2031-05-01 65.1300 265200 2022-09-21 2031-06-01 65.1300 265201 2022-09-21 2031-07-01 65.1300 265202 2022-09-21 2031-08-01 65.1300
需求:若某条记录的Begin Date对应的年度,在同一Market Date分组下没有12个月的完整数据,则将该记录的Settlement值置为0。示例输出如下:
Market Date Begin Date Settlement 0 2016-01-01 2018-01-01 0 1 2016-01-01 2018-02-01 0 2 2016-01-01 2019-01-01 15.2789 3 2016-01-01 2019-02-01 20.7348 4 2016-01-01 2019-03-01 26.1552 5 2016-01-01 2019-04-01 24.1891 6 2016-01-01 2019-05-01 21.7891 7 2016-01-01 2019-06-01 20.7356 8 2016-01-01 2019-07-01 20.2072 9 2016-01-01 2019-08-01 20.2172 10 2016-01-01 2019-09-01 20.2272 11 2016-01-01 2019-10-01 20.2372 12 2016-01-01 2019-11-01 20.2572 13 2016-01-01 2019-12-01 20.2772 14 2016-02-01 2019-01-01 0 15 2016-02-01 2020-01-01 20.25
注:2016年2月1日对应的2020年度有完整数据,未全部展示。要求避免逐行迭代,用更Pythonic的方式实现。
解决方案
利用Pandas的分组和向量化操作,无需循环即可高效完成需求,步骤如下:
1. 标准化日期格式并提取关键字段
先确保日期列为datetime类型,再提取Begin Date的年份和月份,用于后续统计:
import pandas as pd # 转换日期列格式 df['Market Date'] = pd.to_datetime(df['Market Date']) df['Begin Date'] = pd.to_datetime(df['Begin Date']) # 提取年份和月份作为辅助字段 df['begin_year'] = df['Begin Date'].dt.year df['begin_month'] = df['Begin Date'].dt.month
2. 标记完整年度的分组
按Market Date和begin_year分组,统计每个分组下的唯一月份数量,判断是否为完整的12个月:
# 统计每个(Market Date, begin_year)分组的有效月份数 year_month_stats = df.groupby(['Market Date', 'begin_year'])['begin_month'].nunique().reset_index(name='month_count') # 标记该分组是否为完整年度 year_month_stats['is_complete'] = year_month_stats['month_count'] == 12
3. 更新Settlement值
将标记结果合并回原DataFrame,通过向量化操作将非完整年度的Settlement置为0:
# 合并标记字段到原数据 df = df.merge(year_month_stats[['Market Date', 'begin_year', 'is_complete']], on=['Market Date', 'begin_year'], how='left') # 条件赋值:完整年度保留原值,否则置0 df['Settlement'] = df['Settlement'].where(df['is_complete'], 0) # 清理辅助字段(可选) df = df.drop(['begin_year', 'begin_month', 'is_complete'], axis=1)
方案说明
- 全程使用Pandas内置的分组、合并和向量化方法,避免了逐行迭代的低效问题,处理大规模数据集时性能优势显著。
where方法是Pandas中高效的条件赋值工具,直接对整列进行操作,效率远高于循环遍历。
内容的提问来源于stack exchange,提问作者noobcoder
相关产品推荐
相关产品推荐

