应使用 pd.concat() 替代已移除的 hstack/vstack:横向合并用 axis=1(需注意索引对齐,必要时 reset_index),纵向用 axis=0;须显式指定 axis,避免默认 axis=0 导致误用。

用 pd.concat() 替代已废弃的 hstack 和 vstack
这两个函数在 Pandas 0.23 版本后就彻底移除了,现在直接调用会报 AttributeError: module 'pandas' has no attribute 'hstack'。它们原本只是对 pd.concat() 的简单封装,现在必须改用后者,且行为更明确、可控。
关键区别在于:旧函数默认按 axis=1(列方向)拼接 hstack,axis=0(行方向)拼接 vstack;而 pd.concat() 必须显式指定 axis,否则默认是 axis=0 —— 这点容易踩坑。
- 横向合并(原
hstack)→ 用pd.concat([df1, df2], axis=1) - 纵向合并(原
vstack)→ 用pd.concat([df1, df2], axis=0) - 多个 DataFrame 合并时,
pd.concat()支持列表或元组,但不能传入字典(除非用keys参数) - 默认会保留所有索引,导致重复或错位;需要对齐行/列时,加
ignore_index=True或join='inner'
axis=1 合并时索引不匹配的典型表现
横向合并最常出问题:两个 DataFrame 行数相同但索引值不同(比如一个是 [0,1,2],另一个是 [10,11,12]),pd.concat(..., axis=1) 会按索引对齐,结果出现大量 NaN,而不是按位置拼接。
这不是 bug,是设计行为。如果你要严格按行位置拼(不管索引值),必须先重置索引:
pd.concat([df1.reset_index(drop=True), df2.reset_index(drop=True)], axis=1)
- 不重置就拼 → 按索引值对齐,缺失位置填
NaN - 只重置其中一个 → 对齐仍失败,必须两边都重置或都保持原索引
- 想保留原索引又对齐?用
join='outer'(默认)或join='inner'控制连接方式
性能和内存:pd.concat() 不是“越快越好”的操作
它本质是新建 DataFrame,把所有输入数据拷贝进新对象。当合并大表(尤其列数多、行数多)时,内存占用可能翻倍,耗时明显。
- 避免循环中反复调用
pd.concat(),比如一边读 CSV 一边拼 —— 改用list.append()存 DataFrame,最后一次性 concat -
ignore_index=True会重建索引,小数据无感,大数据可能拖慢 10%~20% - 如果只是临时查看效果,用
pd.concat(..., copy=False)可减少一次拷贝(但不保证安全,仅限信任数据源) - 列名重复时,默认保留全部列(变成
col,col.1),不会报错,但后续取列容易出错
替代 vstack 时要注意空 DataFrame 的处理
纵向合并中,如果其中一个 DataFrame 是空的(len(df) == 0),pd.concat(..., axis=0) 默认仍会保留其列结构 —— 但若空 df 的列名和非空 df 不一致,会补 NaN 列,也可能抛 ValueError: All objects passed were None(比如传了 None 而非空 df)。
- 确保所有待合并对象都是非空
pd.DataFrame,可用[df for df in dfs if len(df) > 0]过滤 - 空 df 有列但无行?检查
df.columns是否与其它 df 一致,不一致就先reindex - 合并前统一列顺序:
df = df[common_cols],否则列会错位或新增 - 别依赖
sort=False来提速 —— 它只影响列顺序排序,不影响核心性能
横向合并真正难的不是语法,是索引对齐逻辑;纵向合并真正卡住的往往不是代码,而是空表和列名不一致带来的静默错位。动手前先 print(df.index) 和 print(df.columns.tolist()) 看两眼,省掉一半调试时间。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











