使用Pandas筛选行:跨年份极值数据对比筛选的问题求助
筛选2015年打破历史气温极值的记录
数据背景
我有四组Pandas DataFrame:datamax(2005-2014年最高温)、datamax2015(2015年最高温)、datamin(2005-2014年最低温)、datamin2015(2015年最低温)。数据片段如下:
print(datamax.head()) print(datamin.head()) print(datamax2015.head()) print(datamin2015.head())
数据示例:
datamax前5行:
Date ID Element Data_Value 0 2005-01-01 USW00094889 TMAX 156 1 2005-01-02 USW00094889 TMAX 139 2 2005-01-03 USW00094889 TMAX 133 3 2005-01-04 USW00094889 TMAX 39 4 2005-01-05 USW00094889 TMAX 33
datamin前5行:
Date ID Element Data_Value 0 2005-01-01 USC00200032 TMIN -56 1 2005-01-02 USC00200032 TMIN -56 2 2005-01-03 USC00200032 TMIN 0 3 2005-01-04 USC00200032 TMIN -39 4 2005-01-05 USC00200032 TMIN -94
datamax2015前5行:
Date ID Element Data_Value 0 2015-01-01 USW00094889 TMAX 11 1 2015-01-02 USW00094889 TMAX 39 2 2015-01-03 USW00014853 TMAX 39 3 2015-01-04 USW00094889 TMAX 44 4 2015-01-05 USW00094889 TMAX 28
datamin2015前5行:
Date ID Element Data_Value 0 2015-01-01 USC00200032 TMIN -133 1 2015-01-02 USC00200032 TMIN -122 2 2015-01-03 USC00200032 TMIN -67 3 2015-01-04 USC00200032 TMIN -88 4 2015-01-05 USC00200032 TMIN -155
需求说明
- 针对
datamax与datamax2015:筛选datamax2015中Data_Value大于datamax对应同月同日所有Data_Value的记录,保留符合条件的2015年条目。 - 针对
datamin与datamin2015:筛选datamin2015中Data_Value小于datamin对应同月同日所有Data_Value的记录。
尝试的代码
upper = [] for row in datamax.iterrows(): for j in datamax2015["Data_Value"]: if j > row["Data_Value"]: upper.append(row) lower = [] for row in datamin.iterrows(): for j in datamin2015["Data_Value"]: if j < row["Data_Value"]: lower.append(row)
问题分析与修正方案
原代码的核心问题
- 逻辑完全偏离需求:你现在是把
datamax的每一行和datamax2015的所有Data_Value做无差别对比,完全没有按同月同日匹配,而且最后收集的是datamax的行,不是datamax2015中符合条件的目标记录。 iterrows()使用错误:iterrows()返回的是(index, row)元组,直接用row["Data_Value"]会触发KeyError,得用row[1]["Data_Value"]才能取到值,但哪怕修正这个,逻辑依然不对。- 效率极低:双重循环遍历DataFrame是Pandas的反模式,完全浪费了库的向量化运算优势,大数据集下会慢到难以接受。
正确的实现步骤
我们需要先对历史数据按月-日分组计算极值,再和2015年数据匹配筛选,全程用Pandas的向量化操作完成:
步骤1:统一日期格式,提取月日匹配键
先把所有DataFrame的Date列转为datetime类型,方便提取月日信息:
import pandas as pd # 转换日期列格式 datamax['Date'] = pd.to_datetime(datamax['Date']) datamax2015['Date'] = pd.to_datetime(datamax2015['Date']) datamin['Date'] = pd.to_datetime(datamin['Date']) datamin2015['Date'] = pd.to_datetime(datamin2015['Date']) # 提取月-日作为同日匹配的键 datamax['month_day'] = datamax['Date'].dt.strftime('%m-%d') datamax2015['month_day'] = datamax2015['Date'].dt.strftime('%m-%d') datamin['month_day'] = datamin['Date'].dt.strftime('%m-%d') datamin2015['month_day'] = datamin2015['Date'].dt.strftime('%m-%d')
步骤2:计算历史数据的每日极值
对历史最高温按month_day分组取最大值,历史最低温按month_day分组取最小值:
# 历史同期最高温的每日最大值 historical_max = datamax.groupby('month_day')['Data_Value'].max().reset_index() historical_max.columns = ['month_day', 'historical_max_val'] # 历史同期最低温的每日最小值 historical_min = datamin.groupby('month_day')['Data_Value'].min().reset_index() historical_min.columns = ['month_day', 'historical_min_val']
步骤3:匹配2015年数据并筛选极值记录
把2015年数据和历史极值合并,然后筛选符合条件的记录:
# 筛选2015年打破历史最高温的记录 merged_max = pd.merge(datamax2015, historical_max, on='month_day', how='left') upper_records = merged_max[merged_max['Data_Value'] > merged_max['historical_max_val']].drop(columns=['month_day', 'historical_max_val']) # 筛选2015年打破历史最低温的记录 merged_min = pd.merge(datamin2015, historical_min, on='month_day', how='left') lower_records = merged_min[merged_min['Data_Value'] < merged_min['historical_min_val']].drop(columns=['month_day', 'historical_min_val'])
结果验证
现在upper_records就是2015年最高温超过历史同日极值的记录,lower_records是2015年最低温低于历史同日极值的记录,完全符合需求。比如datamax2015的1月4日数据(Data_Value=44)超过了历史同日最大值39,会被选入upper_records;datamin2015的1月1日数据(Data_Value=-133)低于历史同日最小值-56,会被选入lower_records。
内容的提问来源于stack exchange,提问作者Caledonian26
相关产品推荐
相关产品推荐

