You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于月日匹配Pandas DataFrame并生成阈值比较掩码

问题:按月日匹配两个DataFrame并判断数值是否小于等于阈值

需求概述

我有两个DataFrame:

  • dfr:索引是带年份的日期,包含数值列qq
  • dfr_t:索引仅为月日格式(如01-01),包含阈值列th
    需要按相同月日匹配两者,判断dfr的qq值是否≤对应阈值,生成布尔结果。

数据示例

dfr数据(test.csv)

dates,qq
1900-01-01,1
1900-01-02,2
1900-01-03,3
1900-01-04,1
1900-01-05,2
1901-01-06,5
1901-01-01,2
1901-01-02,2
1901-01-03,1
1901-01-04,4
1901-01-05,5
1901-01-06,6
1902-01-01,7
1902-01-02,1
1902-01-03,1
1902-01-04,2
1902-01-05,4
1902-01-06,5

dfr_t数据(treh.csv)

dates,th
01-01,1
01-02,2
01-03,2
01-04,3
01-05,3
01-06,1

预期结果

1900-01-01  1   01-01   1   True
1900-01-02  2   01-02   2   True
1900-01-03  3   01-03   2   False
1900-01-04  1   01-04   3   True
1900-01-05  2   01-05   3   True
1900-01-06  5   01-06   1   False
1901-01-01  2   01-01   1   False
1901-01-02  2   01-02   2   True
1901-01-03  1   01-03   2   True
1901-01-04  4   01-04   3   False
1901-01-05  5   01-05   3   False
1901-01-06  6   01-06   1   False
1902-01-01  7   01-01   1   False
1902-01-02  1   01-02   2   True
1902-01-03  1   01-03   2   True
1902-01-04  2   01-04   3   True
1902-01-05  4   01-05   3   False
1902-01-06  5   01-06   1   False

当前读取代码

import pandas as pd

dfr   = pd.read_csv('test.csv', sep=',', index_col=0, parse_dates=True)
dfr_t = pd.read_csv('treh.csv', sep=',', index_col=0)

遇到的问题

dfr_t的索引类型为dtype('O'),尝试转换为DatetimeIndex时触发报错:

ValueError: time data "1" doesn't match format "%m-%d", at position 0. You might want to try:
    - passing `format` if your strings have a consistent format;
    - passing `format='ISO8601'` if your strings are all ISO8601 but not necessarily in exactly the same format;
    - passing `format='mixed'`, and the format will be inferred for each element individually. You might want to use `dayfirst` alongside this.

试过复制拼接dfr_t的方法,但通用性差,求合理解决方案。


解决方案

方法1:提取月日字符串作为匹配键

不用转换dfr_t的索引为日期,直接提取dfr索引的%m-%d格式字符串,和dfr_t的索引做匹配:

# 提取dfr索引的月日字符串
dfr['month_day'] = dfr.index.strftime('%m-%d')
# 按月日字符串合并两个DataFrame
merged = dfr.merge(dfr_t, left_on='month_day', right_index=True, how='left')
# 生成布尔结果
merged['result'] = merged['qq'] <= merged['th']
# 整理成预期格式输出
output = merged[['qq', 'month_day', 'th', 'result']]
print(output.to_string(header=False))

方法2:统一转换为虚拟年份的DatetimeIndex

给dfr_t的月日补一个固定年份(比如2000年,非闰年不影响月日匹配),转换为DatetimeIndex,然后提取dfr索引的月日部分做匹配:

# 给dfr_t的月日补年份,转换为DatetimeIndex
dfr_t.index = pd.to_datetime('2000-' + dfr_t.index)
# 提取dfr索引的月日(用2000年统一年份)
dfr['dummy_date'] = dfr.index.map(lambda x: x.replace(year=2000))
# 合并两个DataFrame
merged = dfr.merge(dfr_t, left_on='dummy_date', right_index=True, how='left')
# 生成布尔结果
merged['result'] = merged['qq'] <= merged['th']
# 整理输出格式
merged['month_day'] = merged['dummy_date'].strftime('%m-%d')
output = merged[['qq', 'month_day', 'th', 'result']]
print(output.to_string(header=False))

方法3:用pd.Series.map直接映射阈值

更简洁的方式,把dfr_t转换成字典,然后用map给dfr添加对应阈值,再判断:

# 把dfr_t转换成{月日: 阈值}的字典
th_dict = dfr_t['th'].to_dict()
# 给dfr添加阈值列
dfr['th'] = dfr.index.strftime('%m-%d').map(th_dict)
# 生成布尔结果
dfr['result'] = dfr['qq'] <= dfr['th']
# 整理输出格式
dfr['month_day'] = dfr.index.strftime('%m-%d')
output = dfr[['qq', 'month_day', 'th', 'result']]
print(output.to_string(header=False))

内容的提问来源于stack exchange,提问作者diedro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 12:37:21