【问题标题】:Generate diff of two CSV files based on a single column using Pandas使用 Pandas 基于单列生成两个 CSV 文件的差异
【发布时间】:2021-06-24 19:35:40
【问题描述】:

我正在处理每个数百兆字节(800k+ 行)、使用管道分隔符并有 90 列的 CSV 文件。我需要做的是一次比较两个文件,生成一个包含任何差异的 CSV 文件(即 File2 中不存在于 File1 中的行以及 File1 中不存在于 File2 中的行),但仅使用执行比较单列。

例如,一个高度简化的版本是:

文件1

claim_date|status|first_name|last_name|phone|claim_number
20200501|active|John|Doe|5555551212|ABC123
20200505|active|Jane|Doe|5555551212|ABC321

文件2

claim_date|status|first_name|last_name|phone|claim_number
20200501|active|Someone|New|5555551212|ABC123
20200510|active|Another|Person|5555551212|ABC000

在本例中,输出文件应如下所示:

claim_date|status|first_name|last_name|phone|claim_number
20200505|active|Jane|Doe|5555551212|ABC321
20200510|active|Another|Person|5555551212|ABC000

如本例所示,两个输入文件都包含带有 claim_number ABC123 的行,尽管两个文件中的 first_name 和 last_name 字段发生了变化,但我并不关心,因为两个文件中的 claim_number 相同。其他行包含唯一的 claim_number 值,因此都包含在输出文件中。

我被告知 Pandas 是执行此操作的方法,因此我设置了 Jupyter 环境并且能够正确加载文件,但此时我的头撞到了墙上。任何建议都非常感谢!

到目前为止我的代码:

import os
import pandas as pd

df1 = pd.read_table("/Users/X/Claims_20210607.txt", sep='|', low_memory=False)
df2 = pd.read_table("/Users/X/Claims_20210618.txt", sep='|', low_memory=False)

在这一点上,我写的其他所有内容基本上都无关紧要,因为它只是来自网络的复制粘贴,由于某种原因无法执行。

编辑:解决方案!

import os
import pandas as pd

df1 = pd.read_table("Claims_20210607.txt", sep='|', low_memory=False)
df2 = pd.read_table("Claims_20210618.txt", sep='|', low_memory=False)

df1.astype({'claim_number':'str'})
df2.astype({'claim_number':'str'})

df = pd.concat([df1,df2])
(
    df.drop_duplicates(
        subset=['claim_number'],
        keep = False,
        ignore_index=True)
    .to_csv('diff.csv')
)

在写入文件之前,我仍然需要弄清楚如何关闭第一个/添加的列,但这太棒了!谢谢!

【问题讨论】:

  • 我尝试按照此处的指南进行操作:hackersandslackers.com/compare-rows-pandas-dataframes 但是当我运行它时,生成的错误是“ValueError:您正在尝试在 float64 和对象列上合并。如果您希望继续,您应该使用pd.concat"
  • @Nk03 这似乎生成了一个文件,基本上是两个文件中的所有行
  • 我不认为我理解你的例子。输出不会有三行吗?共有三个唯一的索赔编号。
  • @MarkBaker 发布了 1 个代码 sn-p 作为您可以尝试的答案。
  • @NickODell 每个文件中的第一行都有 claim_number 'ABC123',因此输出文件中省略了整行。 ABC000 仅存在于 File2 中,而 ABC321 仅存在于 File1 中,因此两者都包含在输出中。我希望输出包含所有列,但仅包含 claim_number 仅存在于两个文件之一中的行。

标签: pandas csv


【解决方案1】:

IIUC,你可以试试:

  1. 如果您想根据除['first_name', 'last_name'] 之外的所有列删除重复项:
df = pd.concat([df1, df2])
(
    df.drop_duplicates(
        subset=df.columns.difference(['first_name', 'last_name']),
        keep=False)
    .to_csv('file3.csv')
)
  1. 如果您只想删除基于重复的 claim_number 列的重复项:
df = pd.concat([df1,df2])
(
    df.drop_duplicates(
        subset=['claim_number'],
        keep = False)
    .to_csv('file3.csv')
)

【讨论】:

  • 好吧,这似乎让我接近了!我的文件有 90 列,所以我替换了“first_name”。 'last_name' 包含我不关心的 89 列,它生成了一个包含大约一千行的文件,这些行确实看起来是唯一的!剩下的问题是它并不总是将 claim_number 列视为字符串。例如,claim_number 可能看起来像 20099E10011,并且有时输出文件中有科学记数法,就好像它将值解释为数字一样,即输出文件中的一行包含 2.1158E+264
  • 您的示例 #2 效果很好!同样的问题仍然存在:将某些值解释为科学记数法而不是字符串比较。关于解决这个问题的想法,以及省略输出中的第一列(因为它不是输入文件中的列)
猜你喜欢
  • 1970-01-01
  • 2019-09-21
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 2015-10-15
  • 1970-01-01
相关资源
最近更新 更多