Pandas DataFrame多条件赋值问题:基于市场类型填充月末日期至目标列
Pandas DataFrame多条件赋值问题:基于市场类型填充月末日期至目标列
嗨,我看了你的问题和尝试的代码,发现几个关键小问题,咱们一步步来解决它~
首先明确你的核心需求:
- 当
Market列是EEX或ICE,或者ValuedteTo列是空值时,用Value Dte列对应日期的当月最后一天填充ValuedteTo - 对于
OTC且ValuedteTo已有值的行,保留原数值不变
先分析你代码里的问题
- Lambda列引用错误:你在lambda里用了
df['valueDate_From_'],但apply的lambda参数x是当前行对象,应该取当前行的日期(比如x['Value Dte']),而且要注意列名的大小写/命名一致性——你的DataFrame列名是Value Dte,代码里写的valueDate_From_会导致找不到列报错。 - 日期类型未转换:如果
Value Dte是字符串类型,last_day_of_month函数里的replace方法会直接报错,必须先把日期列转成datetime类型。 - 条件覆盖不全:你只处理了
Market为EEX/ICE的情况,没覆盖ValuedteTo为空的场景。
修正后的完整解决方案
步骤1:导入库并转换日期列类型
先把日期列转成datetime,避免字符串操作报错:
import pandas as pd from datetime import datetime, timedelta # 转换日期列,errors='coerce'把空值转成NaT(datetime类型的空值) df['Value Dte'] = pd.to_datetime(df['Value Dte']) df['ValuedteTo'] = pd.to_datetime(df['ValuedteTo'], errors='coerce')
步骤2:优化月末日期计算函数
你的函数逻辑没问题,加个空值处理更稳妥:
def last_day_of_month(any_day): # 处理传入空值的情况 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)
步骤3:多条件赋值(修正版)
用apply结合lambda,同时覆盖两个触发条件:
df['ValuedteTo'] = df.apply( lambda x: last_day_of_month(x['Value Dte']) if (x['Market'] in ['EEX', 'ICE'] or pd.isna(x['ValuedteTo'])) else x['ValuedteTo'], axis=1 )
可选优化:矢量化操作(大数据量更快)
如果你的DataFrame数据量很大,apply效率偏低,可以用矢量化的np.where替代:
import numpy as np # 先批量计算所有行的月末日期 df['temp_last_day'] = df['Value Dte'].apply(last_day_of_month) # 多条件赋值 df['ValuedteTo'] = np.where( (df['Market'].isin(['EEX', 'ICE'])) | pd.isna(df['ValuedteTo']), df['temp_last_day'], df['ValuedteTo'] ) # 删除临时列 df.drop('temp_last_day', axis=1, inplace=True)
测试后的最终效果
处理后你的DataFrame会变成这样:
| Lot | Contract | Value Dte | ValuedteTo | Market |
|---|---|---|---|---|
| -10 | 2024-03 | 2024-03-01 | 2024-03-31 | EEX |
| 10 | 2024-05 | 2024-05-01 | 2024-05-31 | ICE |
| -25 | 2024-10 | 2024-10-01 | 2024-10-31 | ICE |
| 250 | 2024-11 | 2024-11-01 | 2024-11-10 | OTC |
| 30 | 2024-02 | 2024-02-01 | 2024-02-02 | OTC |
| -10 | 2024-01 | 2024-01-01 | 2024-01-31 | EEX |
| -50 | 2024-09 | 2024-09-01 | 2024-09-30 | OTC |
| -80 | 2024-10 | 2024-10-01 | 2024-10-31 | EEX |
最后再提醒一句:一定要保证代码里的列名和你的DataFrame列名完全一致(包括大小写、空格),不然会出现KeyError哦~
备注:内容来源于stack exchange,提问作者Redfox
相关产品推荐
相关产品推荐

