如何不使用diff,按关键字对比行列数不同的CSV文件
对比两个CSV文件提取新行(不使用diff,支持指定关键字列)
需求说明
对比行列数可能不同的两个CSV文件(old.csv和new.csv),已知文件列标题,内容可包含数字、字符串、特殊字符等。要求不使用diff命令,提取new.csv中与old.csv不同的行(可指定关键字列,只要指定列内容组合在old.csv中不存在,就将该行纳入结果),保留列标题生成result.csv。
示例文件
old.csv
round date first second third fourth fifth sixth 1 2 2021.04 2 45e69 10 16 4565 37 2 3 2021.04 4 15 456as df924 35 4N320 4 5 2021.03 4 43!d9 23 26 29 33
new.csv
round date first second third fourth fifth sixth 0 1 2021.04 1 14 15 24 40 41 1 2 2021.04 2 45e69 10 16 4565 37 2 3 2021.04 4 15 456as df924 35 4N320 3 4 2021.03 10 11 20 21 24325 41 5 6 2021.03 4321 9 2#@6 28 34350 41
预期输出
result.csv
round date first second third fourth fifth sixth 0 1 2021.04 1 14 15 24 40 41 3 4 2021.03 10 11 20 21 24325 41 5 6 2021.03 4321 9 2#@6 28 34350 41
解决方案
方案1:使用Pandas(高效简洁)
适合处理复杂格式和大量数据,支持灵活指定关键字列。
- 先安装Pandas(若未安装):
pip install pandas
- 编写处理脚本:
import pandas as pd # 读取文件,用sep='\s+'适配任意数量空格分隔的格式 old_df = pd.read_csv('old.csv', sep='\s+') new_df = pd.read_csv('new.csv', sep='\s+') # 自定义指定需要对比的关键字列,可修改为需求列名 key_columns = ['first', 'fifth'] # 提取old中关键字列的唯一组合 old_key_set = set(old_df[key_columns].apply(tuple, axis=1)) # 筛选new中关键字组合不在old里的行 new_rows = new_df[new_df[key_columns].apply(tuple, axis=1).isin(old_key_set) == False] # 保存结果,用to_string生成和示例一致的空格对齐格式 with open('result.csv', 'w') as f: f.write(new_rows.to_string(index=False))
方案2:纯Python实现(无需额外依赖)
适合无法安装第三方库的场景,手动处理文件格式。
def parse_csv(file_path): """读取空格分隔的CSV文件,返回标题和行数据""" with open(file_path, 'r', encoding='utf-8') as f: lines = [line.strip() for line in f if line.strip()] header = lines[0].split() rows = [] for line in lines[1:]: cols = line.split() rows.append(dict(zip(header, cols))) return header, rows # 读取两个文件 old_header, old_rows = parse_csv('old.csv') new_header, new_rows = parse_csv('new.csv') # 指定关键字列 key_columns = ['first', 'fifth'] # 构建old的关键字组合集合 old_keys = set() for row in old_rows: key_tuple = tuple(row[col] for col in key_columns) old_keys.add(key_tuple) # 筛选new中的新行 result_rows = [row for row in new_rows if tuple(row[col] for col in key_columns) not in old_keys] # 计算列宽,生成对齐格式 col_widths = {} for col in old_header: max_len = max(len(col), max(len(row[col]) for row in result_rows)) col_widths[col] = max_len # 保存结果 with open('result.csv', 'w', encoding='utf-8') as f: # 写入标题 f.write(' '.join([col.ljust(col_widths[col]) for col in old_header]).rstrip() + '\n') # 写入每行 for row in result_rows: line_parts = [row[col].ljust(col_widths[col]) for col in old_header] f.write(' '.join(line_parts).rstrip() + '\n')
内容的提问来源于stack exchange,提问作者Newborn
相关产品推荐
相关产品推荐

