用+拼接多列字符串时,任意列含NaN会导致整行结果为NaN;应先fillna('')或astype(str)处理,再用str.cat()或apply(join)实现可控拼接。

用 + 拼接多列字符串时,空值(NaN 会直接污染结果
直接写 df['col1'] + df['col2'] + df['col3'] 看似简单,但只要任意一列含 NaN,整行结果就变成 NaN——这是 Pandas 的默认行为,不是 bug,但常被误认为“拼接失败”。
真正的问题是:它不自动跳过空值,也不提供分隔符控制。
实操建议:
- 先用
df.fillna('')补空,再拼接(适合空值可视为“空字符串”的场景) - 若需保留原始
NaN含义(比如后续要过滤),改用df.astype(str)转换后拼接,但注意:NaN会变成字符串'nan',得额外处理:df.fillna('').astype(str) - 加号拼接对非字符串列会报错,务必提前确保类型一致,或统一转
str
str.cat() 是专为多列拼接设计的,但必须传入 Series 列表
str.cat() 本身是 Series.str.cat() 方法,不能直接作用于 DataFrame。常见错误是写成 df[['a','b','c']].str.cat(sep='-') —— 这会报 AttributeError: 'DataFrame' object has no attribute 'str'。
正确做法是把多列合并成一个 Series,再调用 .str.cat():
df['merged'] = df[['col1', 'col2', 'col3']].apply(
lambda row: '-'.join(row.dropna().astype(str)), axis=1
)
或者更简洁地用 str.cat 配合 pd.concat(适合列数固定、性能敏感场景):
df['merged'] = pd.concat([
df['col1'].fillna(''),
df['col2'].fillna(''),
df['col3'].fillna('')
], axis=1).apply(lambda x: '-'.join(x), axis=1)
注意:str.cat() 的 sep 参数只在单 Series 多元素拼接时生效(如 series.str.cat(sep=',')),对多列不直接受用。
用 apply + join 最灵活,但要注意 axis 和 dropna
这是实际项目中最可控的方式,尤其当你要跳过空值、自定义分隔符、甚至加条件逻辑时。
关键点:
-
axis=1表示按行操作,漏掉会默认按列(axis=0),结果完全错误 -
row.dropna()去掉该行中的NaN,避免join报错;若想保留空格占位,改用row.fillna('') - 如果某列是数字型,
str.join()会报错,必须显式转str:row.dropna().astype(str) - 性能上,
apply在大数据量下比向量化慢,但可读性和容错性高得多
别忽略索引对齐问题:拼接后新列长度异常通常是因为索引不一致
如果你从其他 DataFrame 或外部数据中取列来拼接(比如 df1['a'] + df2['b']),即使两列长度相同,只要索引不同(如一个是 RangeIndex,另一个是带缺失的 Int64Index),Pandas 会按索引对齐——导致大量 NaN 或长度变短。
检查方法:
- 打印
df['col1'].index.equals(df['col2'].index),返回False就说明有问题 - 临时对齐:用
df['col1'].values + df['col2'].values(绕过索引,但失去标签语义) - 稳妥做法:统一重置索引
df = df.reset_index(drop=True)再拼接
这个细节在合并多个来源数据时极容易被忽略,最终拼出一列几乎全是 NaN,却查不出原因。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











