匹配和显示行

时间:2012-11-20 21:47:36

标签: python numpy

所以我有2个文件,文件1有4列,有160000行数值数据,文件2有26列,有150000个数值数据。我想知道是否有办法匹配两个文件中相同的值并显示这种匹配的行。我正在尝试减少文件2中的行以匹配文件1的行数。

3 个答案:

答案 0 :(得分:1)

我在这里做了一些假设:

  1. 这两个文件都没有有用的排序顺序,因此没有有效的方法来锁定步骤。

  2. 你有足够的内存用于一组160000个4元组的短字符串。

  3. 您可以按字符串而不是数字进行匹配(例如,您不会在文件1中使用“0013”而在文件2中使用“00013”并期望它们匹配)。如果没有,只需将每个line.split()更改为int(col) for col in line.split()即可。 (这也可能会减少内存使用量,但也可能会降低速度。无论如何,除非出现问题,否则通常会更好。)

  4. 您的格式只不过是以空格分隔的数字。如果它更复杂,请按照acjohnson55的建议使用csv模块。

  5. 匹配列是文件2中的前四列,它们的顺序与文件1中的顺序相同。否则,您需要添加cols = cols[3], cols[14], cols[15], cols[1]之类的内容。

    < / LI>

    如果这些都是很好的假设,那么这就是代码:

    with open(path1, 'r') as f1:
        data = set(tuple(line.split()) for line in f1)
    with open(path2, 'r') as f2, open(outpath, 'w') as f3:
        for line in f2:
            cols = line.split()
            if tuple(cols[:4]) in data:
                f3.write(line + '\n')
    

答案 1 :(得分:1)

在我看来,您想要的是将文件1的每一行作为元组读取,可能使用csv模块,并将每个元组添加到set。然后,对于文件2中的每一行,提取可能与文件1匹配的4列,并检查它们是否在集合中。如果是这样,请将该行写入新的输出文件。

答案 2 :(得分:0)

您可以使用我在回复之前问题时发布的技术,此处:How to vectorize a simple for loop in Python/Numpy

基本上,将这两个文件读入numpy数组,对两个数组进行排序,然后以lockstep进行迭代。其他人描述的基于散列的代码(元组集)几乎肯定会使用比这更多的内存:)哪一个更快,你必须尝试看看。

import numpy as np

def is_less(a, b):
    # this ugliness is needed because we want to compare lexicographically same as np.lexsort(), from the last column backward
    for i in range(len(a)-1, -1, -1):
        if a[i]<b[i]: return True
        elif a[i]>b[i]: return False
    return False

def is_equal(a, b):
    for i in range(len(a)):
        if a[i] != b[i]: return False
    return True

arr1 = np.fromfile('arr1.csv', sep=',')
arr2 = np.fromfile('arr2.csv', sep=',')

idx1 = np.lexsort( arr1.transpose() )
idx2 = np.lexsort( arr2.transpose() )
ii = 0
jj = 0
while ii < len(arr1) and jj < len(arr2):
    a = arr1[ idx1[ii] , : ] # use all columns from this
    b = arr2[ idx2[jj] , 0:4 ] # use only first four columns; or select the right ones with an appropriate slice
    if is_equal( a, b ):
        # do stuff with match
        print "match found: arr1[%d]=%s arr2[%d]=%s" % ( idx1[ii], repr(a), idx2[jj], repr(b) )
        ii += 1
        jj += 1
    elif is_less( a, b ):
        ii += 1
    else:
        jj += 1