如何正确拆分pandas DataFrame两列并保存为CSV文件
问题根因
导出的CSV排版错乱、列拆分失败由几个明确问题导致:
- 你在
to_csv时手动指定了sep='\t',也就是用制表符作为列分隔符,但CSV格式默认分隔符是逗号,绝大多数表格软件打开CSV时会默认按逗号拆分,自然会把两列内容挤在同一列。 groupby聚合时没有加as_index=False参数,导致filename变成了DataFrame的索引而不是普通列,进一步加剧了列结构错位。- 原代码逐行重复提取文件名、反复用列表嵌套再拆值的逻辑完全冗余,会拖慢1000个文件的处理速度,而且原代码只取了YOLO标注行的第2个值(即x_center坐标),如果你需要完整bbox的四个坐标值,原取值逻辑也不符合需求。
修复步骤
- 导出标准CSV时去掉
sep='\t'参数,用默认逗号分隔,兼容性最好,所有表格工具都能自动识别列;如果一定要用制表符分隔,把文件后缀改成.tsv即可被工具自动识别。 - 分组聚合时加上
as_index=False,保证filename作为普通列存在,不要变成索引。 - 简化冗余的列表处理逻辑,把文件名提取放到文件循环外层,不用逐行重复计算。
- 导出时加上
index=False,不要把pandas自动生成的行索引写到文件里。
修正后可直接运行的代码
import os import pandas as pd import glob myFiles = glob.glob('C:\\Users\\xxx\\Sub_Folder\\*.txt') final_df = [] # 预生成24小时时间段映射,不用手写一长串replace参数 time_map = {f"{hour:02d}": f"{hour:02d}:00-{hour:02d}:59" for hour in range(24)} for file_path in myFiles: # 文件名只需要提取一次,不用逐行重复跑 base_name = os.path.basename(file_path) file_num = ''.join([c for c in base_name if c.isdigit()]) with open(file_path, 'rt') as f: for line in f: line = line.strip() if not line: continue parts = line.split() try: # 👉 如果只需要原逻辑的x_center单值,用下面这行 # bbox_val = float(parts[1]) # 👉 如果需要完整bbox(x_center/y_center/width/height四个值),用下面这行 bbox_val = tuple(float(v) for v in parts[1:5]) final_df.append({ "filename": file_num, "bbox": bbox_val }) except: print(f"文件{base_name}存在不符合格式的行,已跳过") # 构建DataFrame df = pd.DataFrame(final_df) # 映射时间段 df['filename'] = df['filename'].replace(time_map) # 去重 df = df.drop_duplicates(subset=['filename', 'bbox'], keep='first') # 分组取最大值,保留filename为普通列 df = df.groupby('filename', as_index=False)['bbox'].max() # 导出标准CSV,不写索引 df.to_csv('C:\\Users\\xxx\\CountingCSV\\total_count.csv', index=False)
验证方法
导出后用记事本打开生成的CSV,能看到每行的filename和bbox值之间用逗号分隔,用Excel、WPS、pandas读取时都会自动拆成两列,不会再出现排版错乱。如果需要制表符分隔的版本,把to_csv参数改成sep='\t',同时把文件后缀改为.tsv即可。
内容的提问来源于stack exchange,提问作者Kukkik
相关产品推荐
相关产品推荐

