2016-12-22 59 views
1

我有2個csv文件(當然,其中之一是.tab),他們都有2列數字。我的工作是遍歷第一個文件的每一行,並查看它是否與第二個文件中的任何行匹配。如果是這樣,我打印一個空行到我的輸出CSV文件。否則,我將'R,R'打印到輸出csv文件。我的當前算法執行下列操作:如何通過非常大的csv文件進行搜索?

  1. 掃描該第二文件的每行(每個兩個整數),去那些兩個整數的位置在二維陣列(因此,如果整數是2和3,I」我們將定位[2,3])並賦值爲1.
  2. 檢查第一個文件的每一行,檢查每一行的兩個整數的位置在數組中的值是否爲1,以及然後將相應的輸出打印到第三個csv文件。

不幸的是,csv文件非常大,所以我在運行時立即得到「MemoryError:」。什麼是掃描大型CSV文件的替代方案?

我正在使用Jupyter Notebook。我的代碼:

import csv 
import numpy 

def SNP(): 
    thelines = numpy.ndarray((6639,524525)) 
    tempint = 0 
    tempint2 = 0 
    with open("SL05_AO_RO.tab") as tsv: 
     for line in csv.reader(tsv, dialect="excel-tab"): 
      tempint = int(line[0]) 
      tempint2 = int(line[1]) 
      thelines[tempint,tempint2] = 1 
    return thelines 

def common_sites(): 
    tempint = 0 
    tempint2 = 0 
    temparray = SNP() 
    print('Checkpoint.') 
    with open('output_SL05.csv', 'w', newline='') as fp: 
     with open("covbreadth_common_sites.csv") as tsv: 
      for line in csv.reader(tsv, dialect="excel-tab"): 
       tempint = int(line[0]) 
       tempint2 = int(line[1]) 
       if temparray[tempint,tempint2] == 1: 
        a = csv.writer(fp, delimiter=',') 
        data = [['','']] 
        a.writerows(data) 
       else: 
        a = csv.writer(fp, delimiter=',') 
        data = [['R','R']] 
        a.writerows(data) 
    print('Done.') 
    return 

common_sites() 

文件: https://drive.google.com/file/d/0B5v-nJeoVouHUjlJelZtV01KWFU/view?usp=sharinghttps://drive.google.com/file/d/0B5v-nJeoVouHSDI4a2hQWEh3S3c/view?usp=sharing

+3

問題可能是這樣的:'numpy.ndarray((6639,524525))'。你不應該使用'ndarray'構造函數,你應該使用'array'或'zeros'。但無論如何,你正在製作一個6639 * 524525陣列的'np.float64',它至少需要'6639 * 524525 * 1e-9 *(64/8)'''27.8585718'演出。但是看看你的文件,它們是** tiny **,你可能只需要將它們加載到內存中,然後遍歷其中的一個,然後檢查這個集合的成員資格。使用可獲得的數字大小的數組可能是實現此目標的最少內存有效方法。 –

回答

2

你真的集本來就不大,但它是相對稀疏。您沒有使用稀疏結構來存儲導致問題的數據。
只需使用元組的set存儲看到的數據,然後在該set查找是O(1),例如:

In [1]: 
    import csv 
    with open("SL05_AO_RO.tab") as tsv: 
     seen = set(map(tuple, csv.reader(tsv, dialect="excel-tab"))) 
    with open("covbreadth_common_sites.csv") as tsv: 
     common = [line for line in csv.reader(tsv, dialect="excel-tab") if tuple(line) in seen] 
    common[:10] 
Out[1]: 
    [['1049', '7280'], ['1073', '39198'], ['1073', '39218'], ['1073', '39224'], ['1073', '39233'], 
    ['1098', '661'], ['1098', '841'], ['1103', '15100'], ['1103', '15107'], ['1103', '28210']] 

10 loops, best of 3: 150 ms per loop 

In [2]: 
    len(common), len(seen) 
Out[2]: 
    (190, 138205) 
1

I have 2 csv files (well, one of them is .tab), both of them with 2 columns of numbers. My job is to go through each row of the first file, and see if it matches any of the rows in the second file. If it does, I print a blank line to my output csv file. Otherwise, I print 'R,R' to the output csv file.

import numpy as np 

f1 = np.loadtxt('SL05_AO_RO.tab') 
f2 = np.loadtxt('covbreadth_common_sites.csv') 

f1.sort(axis=0) 
f2.sort(axis=0) 

i, j = 0, 0 
while i < f1.shape[0]: 
    while j < f2.shape[0] and f1[i][0] > f2[j][0]: 
     j += 1 
    while j < f2.shape[0] and f1[i][0] == f2[j][0] and f1[i][1] > f2[j][1]: 
     j += 1 
    if j < f2.shape[0] and np.array_equal(f1[i], f2[j]): 
     print() 
    else: 
     print('R,R') 
    i += 1 
  1. 加載數據到ndarray來優化存儲器使用
  2. 排序數據
  3. 查找排序數組中的匹配項

總複雜度爲O(n*log(n) + m*log(m)),其中n和m爲輸入文件的大小。

使用set()不會減少每個唯一條目的內存使用量,所以我不建議將它用於大型數據集。