处理结构性不佳的CSV数据时,常会遇到标题行与内容行被拆成两行的情况。本文就用Python内置的csv模块,演示如何精准合并相邻的特定行,同时确保列数不变、输出整洁。
CSV数据里,有些记录会因为格式不规范,把一个完整条目拆成两行来写。比如标题和内容分行,或者属性值散落在相邻行中。这时候要是硬用常规读取方式,数据就会乱套。其实解决思路很简单——手动控制迭代,按需预读下一行,再拼接指定列,跑完一套下来输出列数纹丝不动。
举个例子,假设原始数据长这样:
Superman/, 250lbs, Batman/, 180lbsClark Kent, , Bruce Wayne,
想要的结果是把两行合并成一行四列:Superman/Clark Kent,250lbs,Batman/Bruce Wayne,180lbs
核心做法是:遍历时遇到像 Superman/ 这种“主行”,就主动调用 next(reader) 把下一行抓过来,把对应的列字符串拼起来,然后跳过那个子行,避免重复写入。听起来挺直白,但有几个关键点必须处理好,否则容易翻车。
下面是一段靠谱的实现,带上了错误防护和最佳实践:
import csv# 安全读写:输入与输出文件分离,避免原文件损坏with ( open("input.csv", newline="") as f_in, open("output.csv", "w", newline="") as f_out,): reader = csv.reader(f_in, skipinitialspace=True) # 自动去除字段前导空格 writer = csv.writer(f_out) for row in reader: # 判断是否为需合并的主行(可根据实际业务调整条件) if len(row) >= 3 and row[0].strip().endswith("/"): try: next_row = next(reader) # 预读下一行 # 拼接第0列和第2列(索引从0开始),其余列保持不变 row[0] = row[0].rstrip("/") + next_row[0].strip() if len(next_row) > 2: row[2] = row[2].rstrip("/") + next_row[2].strip() except StopIteration: # 若主行后无子行,保留原样(防数据异常) pass writer.writerow(row)几个绕不开的关键细节
- skipinitialspace=True 几乎是必须的。CSV字段里经常有前导空格,比如
" Batman/",不加这个参数就等着踩坑吧。 - 用 with 上下文管理器管理文件,这是规矩,既保证文件正确关闭,也让代码更清爽。
- 永远先写入新文件(比如
output.csv),确认没问题再替换原文件。直接改原文件风险太大,万一写错了数据就废了。 - next(reader) 会永久推进迭代器——如果主行后面没有子行(比如文件末尾),必须捕获
StopIteration异常,否则程序会直接崩溃。 - 条件判断要够健壮:检查
len(row) >= 3防止索引越界,用.strip()处理空白字符,避免意外匹配失败。 - 如果你需要动态匹配多种模式(不止
"Superman/"),可以把判断逻辑封装成函数,或者用正则表达式识别规律,灵活度更高。
最终生成的 output.csv 会严格保持4列结构,字段间没有多余空格,直接就能丢进后续的数据分析流程。这招在处理日志、报表等半结构化数据时特别实用,值得收藏。