2016-03-14 169 views
3

我想比較兩個包含化學數據的大型csv文件。比較兩個大的csv文件,並用python編寫另一個文件

第一個,「file1」是14 Mb(這不是很重),但第二個,「file2」是3Go(47798771行)。

此文件1的樣本(我們將重點放在第四列,其中包含inchikeys):

MFCD00134034 7440-42-8 B UORVGPXVDQYIDP-UHFFFAOYSA-N 
MFCD01745487 64719-89-7 B1BBBB(BBBBB1[Li])[Li] XZXJQLAKEUKXOT-UHFFFAOYSA-N 
MFCD01310566 19287-45-7 BB QSJRRLWJRLPVID-UHFFFAOYSA-N 
MFCD00011323 10035-10-6 Br CPELXLSAUQHCOX-UHFFFAOYSA-N 
     N(CCNCCCCCCCCCCNCCN(CC)CC)(CC)CC PISAWRHWZGEVPP-UHFFFAOYSA-N 
MFCD01744969 137638-86-9 O(C(=O)C(c1ccccc1)c1ccccc1)c1cc2c(C[[email protected]]3N(CC[[email protected]]2(C)C3C)Cc2ccccc2)cc1 CIRJJEXKLBHURV-MAYWEXTGSA-N 
     O(CCCN1CCCC1)c1ccc(NC(=Nc2ccccc2)c2ccccc2)cc1 KETUBKLQEXFJBX-UHFFFAOYSA-N 
MFCD01694581 3810-31-9 S(CCN(CCSC(N)=N)CCSC(N)=N)C(N)=N GGDUORJVTMUGNU-UHFFFAOYSA-N 
MFCD06794992 60066-94-6 Brc1cc(C(=O)c2ncccc2)c(NC(=O)CNC(=O)[[email protected]@H](N)CCCCN)cc1 NVOGGKXDMDDFEG-HNNXBMFYSA-N 
MFCD06794980 60066-98-0 Brc1cc(C(=O)c2ncccc2)c(NC(=O)CNC(=O)[[email protected]@H](N)CCCNC(N)=N)cc1 LFCYDGUHINTBOJ-AWEZNQCLSA-N 

文件2:

lat_chemical_id stereo_chemical_id source_cid inchikey 
CID100000001 CID000000001 1 RDHQFKQIGNGIED-UHFFFAOYSA-N 
CID100000010 CID000000010 10 AUFGTPPARQZWDO-UHFFFAOYSA-N 
CID100000100 CID000000100 100 UTIBHEBNILDQKX-UHFFFAOYSA-N 
CID100001000 CID000001000 1000 ULSIYEODSMZIPX-UHFFFAOYSA-N 
CID100010000 CID000010000 10000 ZPIFKCVYZBVZIV-UHFFFAOYSA-N 
CID100100000 CID000100000 100000 SPTBIJLJJBZGDY-UHFFFAOYSA-N 
CID101000000 CID001000000 1000000 XTNVYACQOFUTNH-UHFFFAOYSA-N 
CID110000000 CID010000000 10000000 WUGPGGSZFRVGGA-UHFFFAOYSA-N 
CID110000001 CID010000001 10000001 ANOUMYXLUIDQNL-UHFFFAOYSA-N 

我的目標是比較inchikeys,第四行在兩個文件中,看看它們是否相同。然後,當它的情況下,提取所有信息(來自兩個文件),並寫在第三位。

這裏是我的(幼稚)代碼:

#!/usr/bin/env python 
#-*- coding: utf-8 -*- 
###################### 
import numpy as np 
import argparse 
import csv 
################################# 


def compare(tab_data_inchik,stitch,output): 
    dt = open(tab_data_inchik, 'rb') 
    st = open(stitch,'rb') 
    out = open(output,'wb') 
    data = csv.reader(dt, delimiter = '\t') 
    database = csv.reader(st, delimiter = '\t') 
    result = csv.writer(out, delimiter = '\t') 
    for line in data: 
     for row in database: 
      if line[3] == row[3]: 
       result.writerow((line[0],line[1],line[2],row[0],row[1],row[2],row[3]))   

    dt.close() 
    st.close() 
    out.close() 

##############################"" 
if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 
    parser.add_argument("tsv1", help = "Pr Data") 
    parser.add_argument("tsv2", help = "Database") 
    parser.add_argument("output", help = "output file") 
    args=parser.parse_args() 

    compare(args.tsv1,args.tsv2,args.output) 

看來,該計劃甚至沒有達到該數據庫循環的第二行,我想這是因爲該文件是到大,我的方法是機器人優化。也許我應該使用numpy.where(),但我不知道如何。

有沒有辦法讓信息沒有雙循環? 在此先感謝。

+0

沒試過我的新代碼? ?我敢打賭它會在10分鐘內運行。 – FazeL

+0

剛剛嘗試過(我在法國)。奇蹟般有效。非常感謝 –

+0

您的歡迎,完成需要多長時間?如果你可以提供一個基準,它會是膨脹的。 – FazeL

回答

5

問題出在哪裏:
在你的代碼是遍歷行milions,3GB文檔中包含超過4400萬線假定每行平均字符爲68個字符,在14MB的文件,讓假設有超過205000行。
然後行20行將執行44000000 * 205000 = 9.02 * 10^12次。

if line[3] == row[3]: 

單CPU上的常見計算機只能下每秒10^10低級指令運行,Python代碼線通常需要比對於每次執行一條指令多得多。因爲它需要大量的時間用於CPU去完成它

的Python字典的數據結構(哈希表):
一組是一種數據結構,有效地檢查數據的一個單件是否被存儲在它之前或不是在恆定數量的小型CPU指令(這是非常省時)。

如果你使用類似的東西,在一個普通的Intel Core i5或類似的東西上完成需要不到5分鐘的時間。

database_set = dict() 
for row in database: #Loop on the smaller file so we store less in memory. 
    database_set[row[3]] = (row[0],row[1],row[2]) 
for line in data: 
    if line[3] in database_set:  
     row = database_set[line[3]] 

     result.writerow((line[0],line[1],line[2],row[0],row[1],row[2],line[3])) 

如果你想了解如何使用Python套查找here
如果你想知道如何設置完成自己的工作,你可以找到here

+1

在作家中,如果我不做雙重循環,計算機如何知道哪一行可以提供信息? –

+0

@EL Walou EL Walou對於不便之處感到抱歉,我正確編輯了這段代碼,將您想要的數據保存在字典的值中,並在需要時將其輕鬆找到。 – FazeL

2

的問題是,當你遍歷所有的database首次行的,裏面的文件指針databasest)是在文件的結尾,所以你不能再而不明確的移動迭代它回到文件的開頭。這可以使用seek完成。

for line in data: 
    st.seek(0) # Resets the file back to the beginning 
    for row in database: 
     if line[3] == row[3]: 
      # Write output data 

更好的解決方案

取決於database的大小,這可能不是很快由於您正在閱讀的每一行的所有文件中data。您可以考慮將database加載到內存中進行比較。

# Load entire database in 
database_rows = [row for row in database] 

for line in data: 
    for row in database_rows: 
     if line[3] == row[3]: 
      # Write output data 

更好的解決

更好的選擇(因爲datadatabase)將data加載到內存中,並直接從文件中讀取database。要做到這一點,你會扭轉你的循環順序。

data_rows = [row for row in data] 

for row in database: 
    for line in data_rows: 
     if line[3] == row[3]: 
      # Write output data 

此解決方案不會要求您將database加載到內存中。

+0

非常感謝,它似乎有效(程序仍在運行),當它停止時,我會給你確認。 –

相關問題