2013-10-07 3 views
1

У меня есть файл csv с одним столбцом, но 6,2 миллиона строк, все содержащие строки от 6 до 20 символов. Некоторые строки будут найдены в двух экземплярах (или более), и я хочу записать их в новый файл csv - предполагается, что должно быть около 1 миллиона неистовых строк. Вот и все. Однако постоянный поиск через словарь из 6 миллионов записей занимает свое время, и я буду благодарен за любые советы о том, как это сделать. Любой сценарий, который я написал до сих пор, занимает по меньшей мере неделю (!) Для запуска, согласно некоторым таймингам, которые я сделал.Оптимизация поиска в очень больших файлах csv

Первая попытка:

in_file_1 = open('UniProt Trypsinome (full).csv','r') 
in_list_1 = list(csv.reader(in_file_1)) 
out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+') 
out_file_2 = open('UniProt Unique Trypsin Peptides.csv','w+') 
writer_1 = csv.writer(out_file_1) 
writer_2 = csv.writer(out_file_2) 

# Create trypsinome dictionary construct 
ref_dict = {} 
for row in range(len(in_list_1)): 
    ref_dict[row] = in_list_1[row] 

# Find unique/non-unique peptides from trypsinome 
Peptide_list = [] 
Uniques = [] 
for n in range(len(in_list_1)): 
    Peptide = ref_dict.pop(n) 
    if Peptide in ref_dict.values(): # Non-unique peptides 
     Peptide_list.append(Peptide) 
    else: 
     Uniques.append(Peptide) # Unique peptides 

for m in range(len(Peptide_list)): 
    Write_list = (str(Peptide_list[m]).replace("'","").replace("[",'').replace("]",''),'') 
    writer_1.writerow(Write_list) 

Вторая попытка:

in_file_1 = open('UniProt Trypsinome (full).csv','r') 
in_list_1 = list(csv.reader(in_file_1)) 
out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+') 
writer_1 = csv.writer(out_file_1) 

ref_dict = {} 
for row in range(len(in_list_1)): 
    Peptide = in_list_1[row] 
    if Peptide in ref_dict.values(): 
     write = (in_list_1[row],'') 
     writer_1.writerow(write) 
    else: 
     ref_dict[row] = in_list_1[row] 

EDIT: Вот несколько строк из файла CSV:

SELVQK 
AKLAEQAER 
AKLAEQAERR 
LAEQAER 
LAEQAERYDDMAAAMK 
LAEQAERYDDMAAAMKK 
MTMDKSELVQK 
YDDMAAAMKAVTEQGHELSNEER 
YDDMAAAMKAVTEQGHELSNEERR 
+0

Пожалуйста размещаете несколько типичных линий вашего CSV-файл. – unutbu

+1

Проблема в том, что вы читаете весь файл сразу, что ни для кого не подходит. Если вам просто нужно вывести дублированные строки, 'uniq -Di somefile.txt> duplicate_lines.txt' –

+0

Странные значения, разделенные запятыми (csv), где нет ничего, чтобы разделить, хе-хе! Я бы не рассматривал этот файл csv. –

ответ

2

Первый намек: Python имеет поддержку для ленивых оценки, лучше использовать его при работе с огромными наборами данных. Итак:

  • итерация над csv.reader вместо Bulding огромный список в памяти,
  • не строят огромные списки в памяти с диапазонами - использовать enumate(seq) вместо этого, если вам нужно как элемент и индекс , и просто перебирайте элементы вашей последовательности, если вам не нужен индекс.

Второй совет: главный смысл использования dict (Hashtable) является для поиска по ключей, а не значения ... Так что не построить огромный Dict, который используется в качестве списка.

Третий совет: если вы просто хотите сохранить «уже увиденные» значения, используйте Set.

+0

Спасибо! Использование набора и итерация над читателем вместо этого действительно ускорили ситуацию - сценарий теперь занимает около минуты. Мне интересно узнать, почему/как это происходит намного быстрее. Это не просто немного быстрее, но невероятно! – Sajber

+0

Первая очевидная причина: то, как вы использовали dict (главным образом: как массив), означало время поиска O (n) (и с очень большим значением «n»). Используя набор, у вас есть O (1) время поиска. Вторая возможная причина (но это дикая догадка): с размером вашего набора данных, имеющим две копии в вашей памяти (список, затем dict), возможно, съел всю доступную оперативную память и заставил ваш компьютер использовать своп, который смертельно медленный , –

+0

Хорошо, это проясняет! – Sajber

0

Я не очень хорош в Python, поэтому я не знаю, как работает «in», но ваш алгоритм работает в n². Попробуйте отсортировать свой список после прочтения его, используя algo в n log (n), например quicksort, он должен работать лучше. Как только список упорядочен, вам просто нужно проверить, совпадают ли два последовательных элемента списка.

Итак, вы получаете чтение по n, сортировку по n log (n) (в лучшем случае) и сравнение по n.

2

Сделайте это с помощью Numpy. Грубо говоря:

import numpy as np 
column = 42 
mat = np.loadtxt("thefile", dtype=[TODO]) 
uniq = set(np.unique(mat[:,column])) 
for row in mat: 
    if row[column] not in uniq: 
     print row 

Можно даже векторизации выходного каскада с использованием numpy.savetxt и операторами углеродно массива, но это, вероятно, не будет делать очень большую разницу.

0

Хотя я считаю, что решение numpy является лучшим, мне любопытно, можем ли мы ускорить данный пример. Мои предложения:

  • skip csv.Затраты на читатель и просто прочитать строку
  • гь, чтобы пропустить дополнительное сканирования, необходимое для исправления перевода строки
  • использовать больший размер буфера файла (чтение 1Meg, написать 64K, вероятно, хорошо)
  • использовать ключи Dict как индекс - ключ поиск гораздо быстрее, чем значение поиска

Я не NumPy парень, так что я хотел бы сделать что-то вроде

in_file_1 = open('UniProt Trypsinome (full).csv','rb', 1048576) 
out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+', 65536) 

ref_dict = {} 
for line in in_file_1: 
    peptide = line.rstrip() 
    if peptide in ref_dict: 
     out_file_1.write(peptide + '\n') 
    else: 
     ref_dict[peptide] = None 
Смежные вопросы