我正在尝试比较两个包含化学品数据的大型csv文件。
第一个," 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[C@H]3N(CC[C@]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)[C@@H](N)CCCCN)cc1 NVOGGKXDMDDFEG-HNNXBMFYSA-N
MFCD06794980 60066-98-0 Brc1cc(C(=O)c2ncccc2)c(NC(=O)CNC(=O)[C@@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
我的目标是比较两个文件中的第四行,以查看它们是否相同。然后,当它的情况下,提取所有信息(从两个文件)并写第三个。
这是我的(幼稚)代码:
#!/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 :(得分:3)
问题出在哪里:
在你的代码中你循环了数百万行,在3GB文档中包含超过44000000行,假设每行的平均字符是68个字符,在14MB doc中假设有超过205000行。
然后第20行将执行44000000 * 205000 = 9.02 * 10 ^ 12次。
if line[3] == row[3]:
单CPU上的普通计算机每秒只能运行10 ^ 10个低级指令,并且一行python代码通常比单个指令执行要多得多。因为CPU需要花费大量时间才能完成它
Python dict数据结构(哈希表):
集合是一种数据结构,可以有效地检查单个数据是否存储在它之前或不存储在恒定数量的小CPU指令中(这是非常节省时间的)。
如果你使用这样的东西,在普通的英特尔酷睿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]))
答案 1 :(得分:1)
问题在于,当您第一次遍历Scanner scanner = new Scanner(input);
while (true) {
String letters = scanner.findWithinHorizon("\\G\\s*\\[a-zA-Z]+", 0);
if (letters != null) {
System.out.println("letters: " + letters.trim());
} else {
String number = scanner.findWithinHorizon("\\G\\s[+-]?[0-9]+", 0);
if (number != null) {
System.out.println("number: " + number.trim());
} else if (scanner.findWithinHorizon("\\G\\s*\\Z", 0) != null) {
System.out.println("end");
break;
} else {
System.out.println("unrecognized input");
break;
}
}
}
的所有行时,database
(database
)内的文件指针位于文件的末尾这样你就可以在没有先将其显式移回文件开头的情况下再次迭代。这可以使用st
完成。
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
小于data
)将加载database
到内存并直接从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
加载到内存中。