You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python的Pandas对比两个按ID排序的CSV文件

刚好我之前处理过类似的CSV对比需求,给你两个实用的解决方案,根据你的文件大小来选就好~

方案一:高效双指针法(适合大型CSV文件)

因为你的两个CSV都是按ID排序的,用双指针遍历可以避免把整个文件加载到内存,内存占用极低,处理大文件特别高效。

直接上代码:

import csv

# 同时打开所有需要的文件
with open('File1.csv', 'r') as f1, open('File2.csv', 'r') as f2, \
     open('diff.csv', 'w', newline='') as diff_file, \
     open('onlyf1.csv', 'w', newline='') as onlyf1_file, \
     open('onlyf2.csv', 'w', newline='') as onlyf2_file:

    # 初始化CSV读写器
    reader1 = csv.reader(f1)
    reader2 = csv.reader(f2)
    diff_writer = csv.writer(diff_file)
    onlyf1_writer = csv.writer(onlyf1_file)
    onlyf2_writer = csv.writer(onlyf2_file)

    # 跳过并处理表头
    next(reader1)
    next(reader2)
    # 写入diff.csv的自定义表头
    diff_writer.writerow(['ID', 'x1', 'x2', 'diffx', 'y1', 'y2', 'diffy', 'z1', 'z2', 'diffz'])
    # 写入两个仅存文件的表头
    onlyf1_writer.writerow(['ID'])
    onlyf2_writer.writerow(['ID'])

    # 初始化双指针(当前行)
    row1 = next(reader1, None)
    row2 = next(reader2, None)

    # 开始遍历两个文件
    while row1 is not None and row2 is not None:
        id1 = int(row1[0])
        id2 = int(row2[0])

        if id1 == id2:
            # ID在两个文件都存在,计算差值写入diff.csv
            x1, y1, z1 = map(int, row1[1:])
            x2, y2, z2 = map(int, row2[1:])
            diffx = x1 - x2
            diffy = y1 - y2
            diffz = z1 - z2
            diff_writer.writerow([id1, x1, x2, diffx, y1, y2, diffy, z1, z2, diffz])
            # 同时移动两个指针
            row1 = next(reader1, None)
            row2 = next(reader2, None)

        elif id1 < id2:
            # ID只在File1里,写入onlyf1.csv
            onlyf1_writer.writerow([id1])
            row1 = next(reader1, None)

        else:
            # ID只在File2里,写入onlyf2.csv
            onlyf2_writer.writerow([id2])
            row2 = next(reader2, None)

    # 处理其中一个文件遍历完后剩下的行
    while row1 is not None:
        onlyf1_writer.writerow([int(row1[0])])
        row1 = next(reader1, None)
    while row2 is not None:
        onlyf2_writer.writerow([int(row2[0])])
        row2 = next(reader2, None)

代码解释:

  1. 用csv模块处理文件,自动处理CSV的格式细节(比如逗号分隔、带引号的字段),比手动解析靠谱多了。
  2. 双指针逻辑:因为文件是按ID排序的,我们只需要比较当前两个行的ID,根据大小关系决定要处理哪一行,不用回头遍历,效率拉满。
  3. 最后处理剩余行:当其中一个文件先遍历完,把另一个文件剩下的ID写入对应的“仅存”文件。

方案二:直观字典法(适合小型CSV文件)

如果你的文件不大,用字典把其中一个文件的内容存起来,代码会更直观,容易理解和修改。

代码示例:

import csv

# 先把File2的内容加载到字典里,键是ID,值是X/Y/Z的列表
file2_data = {}
with open('File2.csv', 'r') as f2:
    reader = csv.reader(f2)
    next(reader)  # 跳过表头
    for row in reader:
        file2_data[int(row[0])] = row[1:]

# 遍历File1,处理共同ID和仅在File1的ID
with open('File1.csv', 'r') as f1, \
     open('diff.csv', 'w', newline='') as diff_file, \
     open('onlyf1.csv', 'w', newline='') as onlyf1_file:
    reader1 = csv.reader(f1)
    diff_writer = csv.writer(diff_file)
    onlyf1_writer = csv.writer(onlyf1_file)

    next(reader1)  # 跳过表头
    diff_writer.writerow(['ID', 'x1', 'x2', 'diffx', 'y1', 'y2', 'diffy', 'z1', 'z2', 'diffz'])
    onlyf1_writer.writerow(['ID'])

    for row in reader1:
        id1 = int(row[0])
        x1, y1, z1 = map(int, row[1:])
        if id1 in file2_data:
            # 匹配到共同ID,计算差值
            x2, y2, z2 = map(int, file2_data[id1])
            diffx = x1 - x2
            diffy = y1 - y2
            diffz = z1 - z2
            diff_writer.writerow([id1, x1, x2, diffx, y1, y2, diffy, z1, z2, diffz])
            del file2_data[id1]  # 删除已匹配的ID,剩下的就是仅在File2的
        else:
            # ID只在File1里
            onlyf1_writer.writerow([id1])

# 处理仅在File2的ID
with open('onlyf2.csv', 'w', newline='') as onlyf2_file:
    writer = csv.writer(onlyf2_file)
    writer.writerow(['ID'])
    # 因为原文件是排序的,这里对剩下的ID排序后写入,保持顺序一致
    for id2 in sorted(file2_data.keys()):
        writer.writerow([id2])

代码解释:

  1. 先把File2的内容加载到字典,用ID作为键,这样查找起来是O(1)的速度。
  2. 遍历File1的时候,直接查字典就能知道ID是否存在于File2,存在就计算差值,不存在就写入onlyf1.csv。
  3. 最后字典里剩下的ID就是仅在File2的,排序后写入onlyf2.csv(保持和原文件一致的顺序)。

验证结果

用你给出的示例文件测试:

  • diff.csv会生成:
ID x1 x2 diffx y1 y2 diffy z1 z2 diffz
1 10 5 5 20 10 10 30 15 15
5 40 55 -15 50 12 38 60 22 38

(注:你的示例里diff.csv的ID1行x2写的是20,应该是笔误,代码会按照实际文件内容计算差值,如果需要调整差值方向(比如x2-x1),只需要修改diffx = x2 - x1这类代码即可)

  • onlyf1.csv:
ID
3
  • onlyf2.csv:
ID
2

完全符合你的需求~

内容的提问来源于stack exchange,提问作者Devesh Agrawal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:38:48