Pandas中条件日期月差计算的Lambda函数报错排查与解决
问题排查与解决方案
报错原因分析
第一种写法错误
df["end_date"].apply()针对单个元素执行lambda,但你在lambda中引用了整个df["start_date"]列,导致每次返回完整的Series(长度与DataFrame行数一致),而非单个数值。apply要求每个lambda调用返回单个值,最终结果长度与原列不匹配,因此抛出ValueError: Columns must be same length as key。
第二种写法错误
df.apply()默认axis=0,表示对列而非行执行函数,此时lambda中的x代表一列(Series),而非单行数据。x["end_date"]试图在列中查找名为"end_date"的元素,自然找不到,抛出KeyError: 'end_date'。此外,即便修正axis=1,用x["end_date"] is not None判断缺失值也不准确——pandas日期列的缺失值是NaT,而非Python原生None,该判断会失效。
正确实现方案
方案1:向量化操作(推荐,效率更高)
使用np.where实现向量化条件判断,这是pandas处理此类逻辑的最优方式,避免循环/apply带来的性能损耗:
import pandas as pd import numpy as np from datetime import date # 初始化DataFrame df = pd.DataFrame({ "column": ["other", "value", "value", "other", "value"], "created": ["2022-04-19 7:09", "2022-03-16 0:58", "2021-12-10 0:36", "2022-01-29 18:47", "2022-01-21 10:14"] }) # 先将created转为datetime类型(原代码缺失此步骤,会导致dt.date报错) df["created"] = pd.to_datetime(df["created"]) df["start_date"] = df["created"].dt.date.astype("datetime64[ns]") # 优化end_date创建(移除多余循环,直接生成datetime类型) df["end_date"] = df["column"].apply(lambda x: pd.Timestamp(date.today()) if x == "value" else pd.NaT) # 计算duration列 today = np.datetime64("today") df["duration"] = np.where( df["end_date"].notna(), ((df["end_date"] - df["start_date"]) / np.timedelta64(1, "M")).round(1), ((today - df["start_date"]) / np.timedelta64(1, "M")).round(1) )
方案2:修正apply写法(仅作演示,不推荐大数据集)
若坚持使用apply,需指定axis=1按行处理,同时用pd.notna()正确判断日期缺失值:
df["duration"] = df.apply( lambda row: ((row["end_date"] - row["start_date"]) / np.timedelta64(1, "M")).round(1) if pd.notna(row["end_date"]) else ((np.datetime64("today") - row["start_date"]) / np.timedelta64(1, "M")).round(1), axis=1 # 关键参数:指定按行处理 )
内容的提问来源于stack exchange,提问作者JoMcGee
相关产品推荐
相关产品推荐

