Pandas DataFrame条件填充:基于多条件为列赋值月末日期

23次阅读

Pandas DataFrame条件填充:基于多条件为列赋值月末日期

本文详解如何在pandas中根据多个条件(如市场类型为eex/ice且目标列为空)自动填充“月末最后一天”到指定列,并提供可直接运行的函数式与向量化方案。

在实际数据分析项目中,常需基于复合逻辑动态填充DataFrame中的缺失值。本例需求明确:对ValuedteTo列进行条件填充——仅当该列当前为空(NaN)且Market列为’EEX’或’ICE’时,将其设为Value Dte所在月份的最后一天;其余情况(如已有值或市场为’OTC’)则保留原值

首先需确保日期列已正确解析为datetime64类型,否则后续日期运算将失败:

import pandas as pd from datetime import timedelta  # 假设 df 已加载 df['Value Dte'] = pd.to_datetime(df['Value Dte']) df['ValuedteTo'] = pd.to_datetime(df['ValuedteTo'], errors='coerce')  # 空字符串转为 NaT

关键在于准确计算月末日期。原代码中last_day_of_month函数存在两个问题:

  1. 输入参数误用(应传入row[‘Value Dte’]而非df[‘valueDate_From_’]);
  2. 返回值未统一为date类型,导致与ValuedteTo列(datetime64)类型不兼容。

修正后的稳健实现如下:

def last_day_of_month(any_day):     """输入任意日期,返回其所在月份最后一天(date对象)"""     if pd.isna(any_day):         return pd.NaT     next_month = any_day.replace(day=28) + timedelta(days=4)     return (next_month - timedelta(days=next_month.day)).date()  def fill_valuedteto(row):     """按规则填充 ValuedteTo 列"""     if pd.isna(row['ValuedteTo']) and row['Market'] in ['EEX', 'ICE']:         return last_day_of_month(row['Value Dte'])     else:         return row['ValuedteTo']  df['ValuedteTo'] = df.apply(fill_valuedteto, axis=1)

✅ 注意事项: pd.isna() 同时兼容 None、np.nan 和 pd.NaT,比 x is None 或 pd.isnull() 更鲁棒; 使用 row[‘Market’] in [‘EEX’, ‘ICE’] 比多次 == 判断更简洁可扩展; 若需保持ValuedteTo列始终为datetime64类型(便于后续时间运算),可将last_day_of_month返回值改为pd.timestamp(…),或在赋值后统一转换:df[‘ValuedteTo’] = pd.to_datetime(df[‘ValuedteTo’])。

进阶建议:避免apply以提升性能
对于大数据集,推荐使用向量化操作替代apply:

mask = df['ValuedteTo'].isna() & df['Market'].isin(['EEX', 'ICE']) df.loc[mask, 'ValuedteTo'] = (     df.loc[mask, 'Value Dte'] + pd.offsets.MonthEnd(0) ).dt.date  # .dt.date 转为 date 类型;若需 datetime,省略 .date

此方案利用pd.offsets.MonthEnd(0)直接获取月末,无需自定义函数,执行效率显著更高,且代码更简洁专业。

最终结果中,EEX/ICE行的空ValuedteTo将被精确填充为对应Value Dte的月末日期(如2024-03-01 → 2024-03-31),而OTC行及已有值保持不变——完全满足业务逻辑要求。

text=ZqhQzanResources