2012-11-20 46 views
1

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

+4

什么构成匹配,因为文件1有4列,但文件2有26? – acjay

+0

文件1中的4列也在文件2中。匹配是它们具有相同的数值。 – user1821176

+0

他们是否按排序?如果不是,你是否有足够的内存一次读取整个较小的文件(大概是文件1)? – abarnert

回答

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]之类的内容。

如果这些都是很好的假设,下面的代码:

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') 
+0

+1代表实际的代码! – acjay

1

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

+0

使用'csv'而不是'split'可能是一个很好的改进(因为他没有给我们任何实际的输入数据,所以很难猜测......)。 – abarnert

+0

或者只是看到实际的代码@abarnert写道,这几乎完全是我所描述的:) – acjay

0

你可以使用我张贴在回答的技术到一个较早的问题,在这里:How to vectorize a simple for loop in Python/Numpy

基本上,阅读这两个文件到numpy的数组,这两个数组排序,步调一致迭代。其他人描述的基于哈希的代码(元组集合)几乎肯定会使用比这更多的内存:)哪一个更快,你得试试看。

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