如何创建Pandas DataFrame单日非NaN占比≥70%的mask实现合规按天求和
前提准备
首先确保你的DataFrame索引为datetime类型,若未转换先执行如下代码:
import pandas as pd df.index = pd.to_datetime(df.index)
生成符合要求的过滤mask
方案1:逐列独立校验(不同列可保留不同的达标日期)
每个列单独判断所属日期的非NaN占比是否达到70%,仅保留达标日期对应列的数值:
MIN_VALID_RATIO = 0.7 # 小时级数据默认一天24条,若你的观测时段不足24小时可调整该值 HOURS_PER_DAY = 24 # 生成布尔mask,True表示该行所属日期对应列满足非空占比要求 mask = df.groupby(df.index.date).transform( lambda col: col.notna().sum() / HOURS_PER_DAY >= MIN_VALID_RATIO )
方案2:全列统一校验(单日任意一列不达标则排除当天所有数据)
如果要求某一天所有列的非空占比都达标才保留该天全部数据,用如下逻辑:
MIN_VALID_RATIO = 0.7 HOURS_PER_DAY = 24 # 先按天校验整站达标情况 daily_valid = (df.notna().groupby(df.index.date).sum() / HOURS_PER_DAY >= MIN_VALID_RATIO).all(axis=1) # 把天级校验结果映射回原小时级数据的每一行,得到统一mask mask = df.index.date.map(daily_valid)
适配非24小时观测场景的优化方案
如果你的数据存在观测时段限制(比如仅白天观测,夜间无数据属于正常情况),可动态计算每天的应观测行数,避免固定24小时的判断误差:
MIN_VALID_RATIO = 0.7 # 动态统计每天实际有记录的行数作为分母 daily_total = df.groupby(df.index.date).size() # 按天校验全列非空占比 daily_valid = (df.notna().groupby(df.index.date).sum().div(daily_total, axis=0) >= MIN_VALID_RATIO).all(axis=1) mask = df.index.date.map(daily_valid)
后续聚合计算
用生成的mask过滤数据后,再按天求和即可:
# 过滤掉不达标日期的数据 df_valid = df[mask] # 按天求和 daily_sum = df_valid.groupby(df_valid.index.date).sum() # 后续可基于daily_sum计算月度均值等指标
内容的提问来源于stack exchange,提问作者paris kat
相关产品推荐
相关产品推荐

