apply返回NaN或形状错乱的根本原因是自定义函数未处理NaN或返回值不匹配广播预期:需显式检查pd.isna(x)、返回标量或等长可迭代对象,避免修改原数据。

apply 传入函数时为什么返回 NaN 或形状错乱
根本原因通常是自定义函数没处理好输入类型,或者返回值不匹配 apply 的广播预期。比如对一列(Series)用 apply,函数却默认按标量逻辑写,遇到 NaN 就崩;又或者函数返回了长度不一致的列表,pandas 无法对齐成新列。
- 确保函数能安全处理
NaN:显式检查pd.isna(x),别直接调用字符串方法(如x.upper()会报AttributeError) - 返回值必须是标量(生成单个值)或等长可迭代对象(生成新列);若想展开多值,改用
applymap或explode配合pd.Series - 避免在函数里修改原
Series或DataFrame,apply不保证执行顺序,也不承诺原地修改
axis=0 和 axis=1 到底影响什么
axis=0 是按列操作(默认),把每列当一个 Series 传给函数;axis=1 是按行操作,把每行当一个 Series(索引为列名)传入。很多人以为 axis=1 是“对每行做计算”,结果函数里用 row['col_a'] + row['col_b'] 没问题,但一旦列名缺失或有空格,就报 KeyError。
-
axis=0下,函数参数是Series,索引是原 DataFrame 行号,值是该列数据 -
axis=1下,函数参数也是Series,但索引是原 DataFrame 列名,值是该行对应各列的值 - 性能上,
axis=1通常慢得多——pandas 要构造 N 个Series(N 是行数),且无法向量化;能用向量化操作(如df['a'] + df['b'])就别用apply(axis=1)
lambda 里调用自定义函数为啥总报 NameError
不是 lambda 本身的问题,而是作用域没对齐。比如你在 Jupyter cell 里定义了 def clean_phone(x): ...,然后写 df['phone'].apply(lambda x: clean_phone(x)) —— 这没问题;但如果把这段代码放进另一个函数里,而 clean_phone 没声明为 global 或作为参数传入,就会找不到。
- 最稳做法:直接传函数名,别套 lambda ——
df['phone'].apply(clean_phone) - 如果必须用 lambda(比如要固定部分参数),确认函数在当前作用域可见;嵌套函数里要用
nonlocal或闭包捕获 - Jupyter 中重跑 cell 可能导致函数定义丢失,运行前先检查
clean_phone in globals()
apply 后结果类型变 object,数值计算失效怎么办
pandas 推断返回类型时很保守。哪怕你函数里全返回 int,只要中间出现一次 None 或 np.nan,整列 dtype 就退化成 object,后续 .sum()、.mean() 全挂掉。
- 用
convert_dtypes()强制转回合适类型:df['new_col'].apply(my_func).convert_dtypes() - 更可靠的是提前指定输出类型:
df['new_col'].apply(my_func).astype('Int64')(注意是大写的Int64,支持 null) - 避免在函数里混用
None和数字;统一用pd.NA或np.nan,并配合dtype='string'/'boolean'等扩展类型

















