Pandas计算PM2.5小时数据日均值:有效小时数不足18返回NaN
问题背景
我正在处理小时级PM2.5监测数据,需要计算其日均值,原始数据格式如下:
Date pm25 Quality_pm25 576 2020-02-25 00:00:00 22.0 1.00 577 2020-02-25 01:00:00 21.0 1.00 578 2020-02-25 02:00:00 27.0 1.00 579 2020-02-25 03:00:00 24.0 1.00 580 2020-02-25 04:00:00 27.0 1.00 581 2020-02-25 05:00:00 27.0 1.00 582 2020-02-25 06:00:00 27.0 1.00 583 2020-02-25 07:00:00 37.0 1.00 584 2020-02-25 08:00:00 41.0 1.00 585 2020-02-25 09:00:00 -9999.0 4.31 586 2020-02-25 10:00:00 -9999.0 4.31 587 2020-02-25 11:00:00 -9999.0 4.31 588 2020-02-25 12:00:00 -9999.0 4.31 589 2020-02-25 13:00:00 -9999.0 4.31 590 2020-02-25 14:00:00 -9999.0 4.31 591 2020-02-25 15:00:00 -9999.0 4.31 592 2020-02-25 16:00:00 -9999.0 4.31 593 2020-02-25 17:00:00 -9999.0 4.31 594 2020-02-25 18:00:00 -9999.0 4.31 595 2020-02-25 19:00:00 -9999.0 4.31 596 2020-02-25 20:00:00 -9999.0 4.31 597 2020-02-25 21:00:00 -9999.0 4.31 598 2020-02-25 22:00:00 -9999.0 4.31 599 2020-02-25 23:00:00 -9999.0 4.31
当前可用的运行代码如下:
import numpy as np import pandas as pd df = pd.read_csv('Data/estacion_data_calidadaire_25_20200201_20200229.csv', parse_dates=['Date']) df = df[['Date', 'pm25', 'Quality_pm25']] invalid = ((df['Quality_pm25'] >=2.6) | (df['pm25'] == -9999)) valid = (df[~invalid]) mean = valid.groupby(valid['Date'].dt.day)['pm25'].mean() mean = round(mean, 0)
当前代码输出结果:
Date 1 22.0 2 14.0 3 15.0 4 21.0 5 24.0 6 29.0 7 37.0 8 34.0 9 28.0 10 29.0 11 30.0 12 32.0 13 33.0 14 40.0 15 25.0 16 19.0 17 20.0 18 21.0 19 28.0 20 28.0 21 29.0 22 23.0 23 21.0 24 27.0 25 28.0
新增需求
经过下述无效数据过滤规则筛选后,若当日有效数据的小时数不足18,则该日均值返回NaN。
无效数据判断规则:
invalid = ((df['Quality_pm25'] >=2.6) | (df['pm25'] == -9999))
例如样例中的2020-02-25仅存在9小时有效数据,期望该日的均值输出为NaN,预期输出示例:
Date 25 NaN
解决方案
修改思路:分组时同时统计每日有效数据条数,对条数不足18的日期的均值赋值为NaN即可。如果你的数据可能包含多个月份,建议用dt.date分组避免不同月同天数据被合并,单月数据可直接用原逻辑的dt.day分组。
修改后的完整代码:
import numpy as np import pandas as pd df = pd.read_csv('Data/estacion_data_calidadaire_25_20200201_20200229.csv', parse_dates=['Date']) df = df[['Date', 'pm25', 'Quality_pm25']] # 无效数据过滤规则 invalid = ((df['Quality_pm25'] >=2.6) | (df['pm25'] == -9999)) valid = df[~invalid] # 按日分组,同时统计有效数据条数和均值 # 若需保留原输出的日数索引,将dt.date改为dt.day即可 daily_res = valid.groupby(valid['Date'].dt.day)['pm25'].agg([ ('valid_cnt', 'count'), ('avg_pm25', 'mean') ]) # 有效小时数不足18的均值替换为NaN,结果保留整数 daily_res['avg_pm25'] = daily_res.apply( lambda x: round(x['avg_pm25'], 0) if x['valid_cnt'] >= 18 else np.nan, axis=1 ) # 转换为和原输出格式一致的Series mean = daily_res['avg_pm25']
运行后25号的结果会自动变为NaN,符合需求。
内容的提问来源于stack exchange,提问作者MANUEL RODRÍGUEZ
相关产品推荐
相关产品推荐

