【问题标题】:Python : Compare two csv files and print out differencesPython:比较两个 csv 文件并打印出差异
【发布时间】:2016-12-24 01:49:36
【问题描述】:

我需要比较两个 CSV 文件并在第三个 CSV 文件中打印出差异。 在我的例子中,第一个 CSV 是一个名为 old.csv 的旧哈希列表,第二个 CSV 是包含新旧哈希的新哈希列表。

这是我的代码:

import csv
t1 = open('old.csv', 'r')
t2 = open('new.csv', 'r')
fileone = t1.readlines()
filetwo = t2.readlines()
t1.close()
t2.close()

outFile = open('update.csv', 'w')
x = 0
for i in fileone:
    if i != filetwo[x]:
        outFile.write(filetwo[x])
    x += 1
outFile.close()

第三个文件是旧文件的副本,而不是更新文件。 怎么了 ?我希望你能帮助我,非常感谢!

PS : 我不想使用 diff

【问题讨论】:

  • 不是答案,而是注释:在 Linux 下,您可以在命令行上简单地执行 diff file1 file2
  • 对不起,我不想使用 difflib
  • 您需要更准确地了解“差异”是什么以及如何打印它。什么是旧文件中有一行但新文件中没有?如果一行在新文件中但不在旧文件中?如果两个连续的行被交换?如果一条线移动到另一个位置?例如,诸如此类的细节使得比较 DNA 序列变得困难,但您需要确定您在问题中的确切含义。
  • @Chris_Rands 因为我需要再次使用 CSV 来处理 SQL 插入等其他事情。

标签: python csv


【解决方案1】:

问题是您将fileone 中的每一行与filetwo 中的同一行进行比较。一旦一个文件中多了一行,你就会发现这些行再也不会相等了。试试这个:

with open('old.csv', 'r') as t1, open('new.csv', 'r') as t2:
    fileone = t1.readlines()
    filetwo = t2.readlines()

with open('update.csv', 'w') as outFile:
    for line in filetwo:
        if line not in fileone:
            outFile.write(line)

【讨论】:

  • @NickYellow 没问题。仅供参考,通常最好的做法是使用 with open() as 语句打开文件,以便在发生任何错误时正确关闭它们。
【解决方案2】:

你可能会发现这个包很有用(csv-diff):

pip install csv-diff

安装后,您可以从命令行运行它:

csv-diff one.csv two.csv --key=id

【讨论】:

  • 很棒的库 - 易于使用且数据输出良好
  • 如何导入?用于 jupyter 笔记本
  • @SnehaaGanesan github.com/simonw/csv-diff 有用作 python 库的示例
【解决方案3】:

使用集合检测差异感觉很自然。

#!/usr/bin/env python3

import sys
import argparse
import csv


def get_dataset(f):
    return set(map(tuple, csv.reader(f)))


def main(f1, f2, outfile, sorting_column):
    set1 = get_dataset(f1)
    set2 = get_dataset(f2)
    different = set1 ^ set2

    output = csv.writer(outfile)

    for row in sorted(different, key=lambda x: x[sorting_column], reverse=True):
        output.writerow(row)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('infile', nargs=2, type=argparse.FileType('r'))
    parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
    parser.add_argument('-sc', '--sorting-column', nargs='?', type=int, default=0)

    args = parser.parse_args()

    main(*args.infile, args.outfile, args.sorting_column)

【讨论】:

    【解决方案4】:

    我假设您的新文件和旧文件一样,只是在旧文件之间添加了一些行。两个文件中的旧行存储顺序相同。

    试试这个:

    with open('old.csv', 'r') as t1:
        old_csv = t1.readlines()
    with open('new.csv', 'r') as t2:
        new_csv = t2.readlines()
    
    with open('update.csv', 'w') as out_file:
        line_in_new = 0
        line_in_old = 0
        while line_in_new < len(new_csv) and line_in_old < len(old_csv):
            if old_csv[line_in_old] != new_csv[line_in_new]:
                out_file.write(new_csv[line_in_new])
            else:
                line_in_old += 1
            line_in_new += 1
    
    • 请注意,我使用了上下文管理器with 和一些有意义的变量名称,这使得它立即更容易理解。而且您不需要 csv 包,因为您在这里没有使用它的任何功能。
    • 关于您的代码,您几乎做对了,除了_您不能转到旧 CSV 中的下一行,除非您在两个 CSV 中读取相同的内容。也就是说,如果你找到一个新的行,继续阅读新文件,直到你偶然发现一个旧文件,然后你就可以继续阅读。

    更新: 这个解决方案不如 Chris Mueller's one 漂亮,它对于小文件来说是完美且非常 Pythonic,但它只读取文件一次(保持原始算法的想法),因此如果你有更大的文件会更好。

    【讨论】:

      【解决方案5】:
      with open('first_test_pipe.csv', 'r') as t1, open('validation.csv', 'r') as t2:
          filecoming = t1.readlines()
          filevalidation = t2.readlines()
      
      for i in range(0,len(filevalidation)):
          coming_set = set(filecoming[i].replace("\n","").split(","))
          validation_set = set(filevalidation[i].replace("\n","").split(","))
          ReceivedDataList=list(validation_set.intersection(coming_set))
          NotReceivedDataList=list(coming_set.union(validation_set)- 
          coming_set.intersection(validation_set))
          print(NotReceivedDataList)
      

      【讨论】:

        【解决方案6】:
        import pandas as pd
        import sys
        import csv
        
        def dataframe_difference(df1: pd.DataFrame, df2: pd.DataFrame, csvfile, which=None):
            """Find rows which are different between two DataFrames."""
            comparison_df = df1.merge(
                df2,
                indicator=True,
                how='outer'
            )
            if which is None:
                diff_df = comparison_df[comparison_df['_merge'] != 'both']
            else:
                diff_df = comparison_df[comparison_df['_merge'] == which]
            diff_df.to_csv(csvfile)
            return diff_df
        
        
        if __name__ == '__main__':
            df1 = pd.read_csv(sys.argv[1], sep=',')    
            df2 = pd.read_csv(sys.argv[2], sep=',')
        
            df1.sort_values(sys.argv[3])
            df2.sort_values(sys.argv[3])
            #df1.drop(df1.columns[list(map(int, sys.argv[4].split()))], axis = 1, inplace = True)
            #df2.drop(df2.columns[list(map(int, sys.argv[4].split()))], axis = 1, inplace = True)
        
            print(dataframe_difference(df1, df2, sys.argv[5]))
        

        使用运行

        python3 script.py file1.csv file2.csv some_common_header_to_sort_each_file output_file.csv
        

        如果您想从比较中删除任何列,请取消注释 df.drop 部分并运行

        python3 script.py file1.csv file2.csv some_common_header_to_sort_each_file "x y z..." output_file.csv
        

        x,y,z 是要删除的列号,索引从 0 开始。

        【讨论】:

          【解决方案7】:

          感谢@vishnoo-rath 在上述答案之一下的评论,提供指向以下页面的链接: https://github.com/simonw/csv-diff#as-a-python-library

          from csv_diff import load_csv, compare
          diff = compare(
              load_csv(open("one.csv"), key="id"),
              load_csv(open("two.csv"), key="id")
          )
          

          【讨论】:

            猜你喜欢
            • 2013-06-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-08
            • 1970-01-01
            • 1970-01-01
            • 2019-05-15
            • 2019-08-03
            相关资源
            最近更新 更多