结论:用pandas.concat()拼接后drop_duplicates(subset=..., keep='last')保留最新行,但“最新”取决于数据中时间字段(需转datetime后排序)或可控的读入顺序;无时间列时需确保文件按修改时间/命名规则有序读取,否则结果不可靠。

直接说结论:用 pandas.concat() 拼接 + drop_duplicates(subset=..., keep='last') 保留最新行,但关键在“最新”的定义方式——它不看文件修改时间,只认数据里的时间字段或读入顺序。
怎么定义“最新”?先确认你的数据有没有时间标识
如果每张 CSV 里都有 update_time、timestamp 或 date 这类列,那是最稳妥的方式;如果没有,就只能靠读入顺序(后读的覆盖先读的),但这很脆弱——文件名乱序、os.listdir() 返回顺序不可靠都会出错。
- 有明确时间列:按该列排序后再去重,
keep='last'才真代表“最新” - 无时间列但能控制读入顺序:确保按文件修改时间或命名规则升序读取,再拼接后
drop_duplicates(..., keep='last') - 完全没线索:别硬凑“最新”,先加一列
source_file和load_order,否则后续无法溯源
用 pd.concat() 拼接时,列对齐容易出什么问题?
散落的 CSV 很可能列名大小写不一致(ID vs id)、多空格(" user_id ")、甚至缺列。pandas 默认按列名对齐,名字不一致就变成 NaN,而不是自动合并。
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
- 统一列名:读取时用
columns=[...]强制指定,或读完用df.columns = df.columns.str.strip().str.lower() - 补缺失列:拼接前对每个
DataFrame调用reindex(columns=common_cols, fill_value=pd.NA) - 别依赖
ignore_index=True掩盖索引混乱——它只是重编号,不解决逻辑重复
为什么 drop_duplicates(keep='last') 有时不生效?
常见原因是去重键(subset)选错了。比如想按用户 ID 保留最新记录,却漏写了 subset=['user_id'],默认会拿整行比,只要任一字段不同就不算重复。
立即学习“Python免费学习笔记(深入)”;
- 必须显式传
subset,且值要稳定可比(避免用含 NaN 的列) - 如果时间列是字符串(如
"2024-03-15"),得先转成datetime再排序,否则字典序比较会出错("2024-01-10" > "2024-03-1"不成立) - 去重前务必
sort_values(by=time_col),否则keep='last'只取最后出现的那条,不保证是时间上最新的
真正麻烦的不是代码几行,而是你得先花时间检查三件事:每张表的列名是否实际等价、时间字段是否真实可用、重复逻辑是否符合业务含义——机器不会替你判断哪一行才算“最新”。

















