如何基于月日匹配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
相关产品推荐
相关产品推荐

