glob比os.listdir更省心,支持递归匹配和路径自动处理;pd.concat不会自动跳过重复表头,需显式控制header/skiprows;大数据量应流式读取再concat,避免内存溢出;列顺序不一致会导致数据错位,须统一列序或校验。

用 glob 找文件比 os.listdir 更省心
直接写 glob.glob("*.csv") 就能拿到当前目录下所有 CSV 路径,不用再手动过滤后缀或拼接路径。如果文件在子目录里,用 glob.glob("data/**/*.csv", recursive=True) 也能一层抓全。注意:Windows 下路径分隔符是反斜杠,但 glob 返回的路径字符串统一用正斜杠或双反斜杠,pandas.read_csv 能直接认,别自己 replace 成单反斜杠——容易出错。
pd.concat 默认不跳过标题行,必须显式控制
很多人以为 pd.concat 会自动识别并丢掉后续文件的表头,其实不会。它只是把每个 DataFrame 当作完整数据块堆叠。所以常见错误是合并后出现几十个重复的首行,比如 “name,age” 出现十次。正确做法是:第一个文件正常读(header=0),其余文件加 header=0 + skiprows=1,或者统一用 header=None 然后手动设列名:
- 方案一(推荐):先读第一个文件获取列名
cols = pd.read_csv(files[0], nrows=0).columns,后面所有文件都用pd.read_csv(f, header=None, skiprows=1, names=cols) - 方案二(简洁):全部用
header=None,最后用df.iloc[0]设第一行为列名,再df = df.iloc[1:].reset_index(drop=True)
内存不够时,别一次性全读进 DataFrame
处理几十万行 × 数十个文件时,pd.concat([pd.read_csv(f) for f in files]) 会先把所有文件加载到内存,极易爆掉。应该流式读取、逐个拼接:
- 用空列表收集每个
DataFrame:dfs = [],循环中dfs.append(pd.read_csv(f, ...)) - 最后只调一次
pd.concat(dfs, ignore_index=True)——比反复df = pd.concat([df, new_df])快一个数量级 - 如果连单个文件都大到吃内存,就用
chunksize分块读,再对每块做concat,但要注意去重和索引连续性
列顺序不一致会导致 concat 合并错位
即使所有 CSV 文件“看起来结构相同”,只要某一个文件的列顺序不同(比如 A.csv 是 id,name,age,B.csv 是 name,id,age),pd.concat 就会按列名对齐,导致数据串列。这不是 bug,是设计行为。解决方法只有两个:
- 读取时强制统一列顺序:
df = pd.read_csv(f)[["id", "name", "age"]] - 或用
pd.concat(..., join="inner")只保留共有的列,再手动补缺失列(适合列集不完全一致的场景)
实际项目里,建议在读取后加一行校验:assert list(df.columns) == expected_cols,比事后排查错位数据省太多时间。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











