如何合并带时间表头的多个CSV文件并匹配对应数据?
多时间表头CSV文件合并方案
问题需求
有多个CSV文件,第一行是时间表头,第二行是对应数据(数据列数比表头多1,最后一个值为固定的0)。需要将所有文件合并为一个CSV,要求:
- 表头包含所有文件出现过的时间戳(可选择去重或保留重复,示例保留重复),同时保留每个数据行的最后一个0
- 每个源文件的数据行在合并后对应一行,匹配到对应时间戳的位置填值,其余位置留空
- 方案需适配任意数量的文件及边缘场景,不能硬编码
示例源文件
file1.csv
15:06:00,16:06:00,00:06:00,18:06:00 111,133,166,126,0
file2.csv
15:08:00,16:08:00,17:06:00,18:06:00 123,133,166,126,0
file3.csv
15:06:00,16:06:00,17:08:00,18:08:00 123,133,166,126,0
预期合并结果
15:06:00,15:08:00,16:06:00,16:08:00,17:06:00,17:08:00,18:06:00,18:08:00,00:06:00,18:06:00,extra 111,,133,,,,,,166,126,0 ,123,,133,166,,126,,,,0 123,,133,,,166,,126,,,0
(注:最后一列命名为extra用于统一存放每行末尾的0,也可根据需求调整格式)
现有代码问题分析
你提供的Pandas代码存在两个核心问题:
- 丢失数据行最后一个值:源文件数据行比表头多一列(最后的0),但代码用
zip(header, data_row)匹配时,仅处理了与表头数量对应的前几个值,最后一个0被丢弃 - 未适配重复时间戳场景:预期结果中保留了重复的时间戳列,但原代码的去重逻辑会过滤掉重复值,无法匹配预期格式
改进后的Pandas解决方案
import pandas as pd file_paths = ['file1.csv', 'file2.csv', 'file3.csv'] all_timestamps = [] data_records = [] for path in file_paths: # 手动读取第一行作为时间表头,避免列数不匹配问题 with open(path, 'r') as f: headers = f.readline().strip().split(',') # 读取第二行数据,分割为列表 data = pd.read_csv(path, skiprows=1, header=None).iloc[0].tolist() # 分离时间对应的数据和末尾的额外值 time_value_map = dict(zip(headers, data[:-1])) extra_value = data[-1] # 收集所有时间表头(保留重复,如需去重则替换为list(dict.fromkeys(headers))) all_timestamps.extend(headers) data_records.append((time_value_map, extra_value)) # 构建合并后的表头,添加额外列存放末尾的0 merged_headers = all_timestamps + ['extra'] master_df = pd.DataFrame(columns=merged_headers) for time_map, extra in data_records: # 初始化空行,空值用空字符串填充 row = pd.Series(index=merged_headers, data='') # 填充时间戳对应的值,适配重复列场景 for ts, val in time_map.items(): for col_idx, col_name in enumerate(merged_headers): if col_name == ts: row.iloc[col_idx] = val # 填充末尾的额外值 row['extra'] = extra # 将行添加到主DataFrame master_df = pd.concat([master_df, row.to_frame().T], ignore_index=True) # 保存结果,空值输出为空字符串 master_df.to_csv('merged_file.csv', index=False, na_rep='')
代码说明
- 手动读取表头:避免Pandas自动处理列数不匹配的问题,准确获取每个文件的时间表头
- 分离数据与额外值:明确拆分时间对应的数据和最后的0,确保不丢失关键数据
- 适配重复时间戳:遍历所有列名匹配时间戳,填充对应位置的值,满足预期格式要求
- 空值处理:用
na_rep=''确保空位置输出为空字符串,符合示例格式
轻量原生Python解决方案(无需Pandas)
如果处理小文件,也可以用原生Python实现,逻辑更直观:
file_paths = ['file1.csv', 'file2.csv', 'file3.csv'] all_headers = [] all_data = [] for path in file_paths: with open(path, 'r') as f: header = f.readline().strip().split(',') data = f.readline().strip().split(',') all_headers.extend(header) # 存储时间-值映射和末尾的额外值 all_data.append((dict(zip(header, data[:-1])), data[-1])) # 构建合并后的表头 merged_header = all_headers + ['extra'] # 生成每一行数据 merged_rows = [] for time_map, extra in all_data: row = [] # 填充时间戳对应的值,空值填空字符串 for col in merged_header[:-1]: row.append(time_map.get(col, '')) # 填充末尾的额外值 row.append(extra) merged_rows.append(','.join(row)) # 写入合并后的文件 with open('merged_file.csv', 'w') as f: f.write(','.join(merged_header) + '\n') f.write('\n'.join(merged_rows))
说明
- 完全依赖原生Python,无需额外库,适合轻量场景
- 逻辑清晰,直接映射时间戳到对应列,空值处理简单
- 支持保留重复时间戳或去重(去重只需将
merged_header改为list(dict.fromkeys(all_headers)) + ['extra'])
内容的提问来源于stack exchange,提问作者dsapprentice
相关产品推荐
相关产品推荐

