【问题标题】:How to Compare 2 very large matrices using Python如何使用 Python 比较 2 个非常大的矩阵
【发布时间】:2010-09-21 13:14:46
【问题描述】:

我有一个有趣的问题。

我有一个非常大(大于 300MB,文件中超过 10,000,000 行/行)的 CSV 文件,其中包含时间序列数据点。每个月我都会收到一个新的 CSV 文件,它与之前的文件几乎相同,除了添加和/或删除了几行新行,并且可能修改了几行。

我想使用 Python 来比较这 2 个文件,并确定哪些行被添加、删除和修改。

问题是文件非常大,所以我需要一个能够处理大文件大小并在合理时间内高效执行的解决方案,越快越好。

文件及其新文件的外观示例:

旧文件
A,2008-01-01,23
A,2008-02-01,45
B,2008-01-01,56
B,2008-02-01,60
C,2008-01-01,3
C,2008-02-01,7
C,2008-03-01,9
etc...

新文件
A,2008-01-01,23
A,2008-02-01,45
A,2008-03-01,67 (已添加)
B,2008-01-01,56
@ 987654333@ (删除和添加)
C,2008-01-01,3
C,2008-02-01,7
C,2008-03-01,22 (修改)
etc... p>

基本上这2个文件可以看作是需要比较的矩阵,我已经开始考虑使用PyTable了。任何有关如何解决此问题的想法将不胜感激。

【问题讨论】:

  • 您能告诉我们更多关于您是如何决定“修改”还是“添加”的信息吗?它是基于日期的吗?
  • 对不起,“修改”我的意思是只有最后一列的值发生了变化。所以 series_id(第一列)和 date(第二列)保持不变。

标签: python django matrix data-structures


【解决方案1】:

像这样。

步骤 1. 排序。

第 2 步。读取每个文件,进行逐行比较。将差异写入另一个文件。

您可以自己轻松编写。或者您可以使用difflibhttp://docs.python.org/library/difflib.html

请注意,一般解决方案非常慢,因为它会搜索差异附近的匹配行。编写自己的解决方案可以运行得更快,因为您知道文件应该如何匹配。您可以优化“差异后重新同步”算法。

10,000,000 行并不重要。它不是那么大。两个 300Mb 的文件很容易放入内存中。

【讨论】:

    【解决方案2】:

    这有点幼稚,但会处理未排序的数据:

    import csv
    
    file1_dict = {}
    file2_dict = {}
    
    with open('file1.csv') as handle:
        for row in csv.reader(handle):
            file1_dict[tuple(row[:2])] = row[2:]
    
    with open('file2.csv') as handle:
        for row in csv.reader(handle):
            file2_dict[tuple(row[:2])] = row[2:]
    
    with open('outfile.csv', 'w') as handle:
        writer = csv.writer(handle)
        for key, val in file1_dict.iteritems():
            if key in file2_dict:
                #deal with keys that are in both
                if file2_dict[key] == val:          
                    writer.writerow(key+val+('Same',))
                else:
                    writer.writerow(key+file2_dict[key]+('Modified',))
                file2_dict.pop(key)
            else:
                writer.writerow(key+val+('Removed',))
        #deal with added keys!  
        for key, val in file2_dict.iteritems():
            writer.writerow(key+val+('Added',))
    

    您可能无法“加入”此解决方案,但它应该可以帮助您完成大约 95% 的工作。 @S.Lott 是对的,2 300mb 文件将很容易放入内存中......如果您的文件进入 1-2gb 范围,那么这可能必须在假设数据已排序的情况下进行修改。

    这样的事情很接近......尽管您可能必须更改比较以使添加的修改变得有意义:

    #assumming both files are sorted by columns 1 and 2
    import datetime
    from itertools import imap
    
    def str2date(in):
        return datetime.date(*map(int,in.split('-')))
    
    def convert_tups(row):
        key = (row[0], str2date(row[1]))
        val = tuple(row[2:])
        return key, val
    
    with open('file1.csv') as handle1:
        with open('file2.csv') as handle2:
            with open('outfile.csv', 'w') as outhandle:
                writer = csv.writer(outhandle)
                gen1 = imap(convert_tups, csv.reader(handle1))
                gen2 = imap(convert_tups, csv.reader(handle2))
                gen2key, gen2val = gen2.next()      
                for gen1key, gen1val in gen1:
                    if gen1key == gen2key and gen1val == gen2val:
                        writer.writerow(gen1key+gen1val+('Same',))
                        gen2key, gen2val = gen2.next()
                    elif gen1key == gen2key and gen1val != gen2val:
                        writer.writerow(gen2key+gen2val+('Modified',))
                        gen2key, gen2val = gen2.next()
                    elif gen1key > gen2key:
                        while gen1key>gen2key:
                            writer.writerow(gen2key+gen2val+('Added',))
                            gen2key, gen2val = gen2.next()
                    else:
                        writer.writerow(gen1key+gen1val+('Removed',))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多