Форум сайта python.su
Всем доброго дня!
Уважаемые Питонщики, мне необходима Ваша помощь.
Имеется большой текстовый файл, размером 4Gb. В нем содержатся строки вида
sid0014 | http://gagaga.com/num=0310103&id=22556756 | pid=2346786
sid0048 | http://gagaga.com/num=045345345&id=22553425 | pid=567456
sid0093 | http://gagaga.com/num=126654&id=225534756 | pid=867546433
sid00235345634 | http://gagaga.com/num=0310103&id=22556756 | pid=3425457785343
….
Таких строк в файле более 4 млн. штук.
Мне нужно найти все строки с совпадающими ссылками и объединить первые и последние значения (разделитель “|”)
Например из строчек выше нужно получить
sid0014, sid00235345634 | http://gagaga.com/num=0310103&id=22556756 | pid=2346786, pid=3425457785343
т.к ссылка в верхней строке, совпадает с нижней.
В общем моих знаний питона хватило на то, чтобы написать цикл в цикле. Т.е. на каждой из 4 млн. строк (итераций) мне приходится пробегаться по всем строкам и выбирать нужные мне данные.
Немного оптимизировал код, теперь при каждой итерации я начинаю проход не с первой строки, а с предыдущей в первом цикле (т.е. отбрасываю то, что уже обработано). Но это не намного ускорило код.
Теперь подсчеты:
В среднем каждая моя итерация основного цикла обрабатывается 40 сек. Т.е. чтобы отработать 4 000 000 итераций мне нужно примерно 44 444 часов. (((
Докупил оперативки, думал загружать весь файл в список и потом с ним работать, но скорость почему-то не выросла. Вопрос - ПОЧЕМУ? Оперативки 8GB - файл 4GB.
Ребята, выручите! Как правильно устроить циклы для реальной работы. Т.к. Таких файлов у меня будет около 60 штук.
Заранее СПАСИБО!
Офлайн
SeganapaА написанный вами код где?
В общем моих знаний питона хватило на то, чтобы написать цикл в цикле
Отредактировано doza_and (Авг. 21, 2014 09:45:40)
Офлайн
#!/usr/bin/env python # -*- coding: utf-8 -*- from grab import Grab import re from grab.selector import XpathSelector from lxml.html import fromstring import lxml.etree from sys import stdin f = open('/home/oleg/Рабочий стол/Parser/proba.csv') output = open('/home/oleg/Рабочий стол/Parser/result.csv', 'w') filespisok = f.readlines() f.close() seen = [] for i, g in enumerate(filespisok): url = g.split("|")[1] if seen.count(url) == 0: seen.append(url) taxonomy = [] taxonomy2 = [] for i1, g1 in enumerate(filespisok): if i1 >= i: if url == g1.split("|")[1]: if taxonomy.count(g1.split("|")[0]) == 0: taxonomy.append(g1.split("|")[0]) if taxonomy2.count(g1.split("|")[2]) == 0: taxonomy2.append(g1.split("|")[2].replace("\n","")) stroka = g.split("|") taxonomy = '%s' % ','.join(taxonomy) taxonomy2 = '%s' % ','.join(taxonomy2) stroka[0] = taxonomy stroka[2] = taxonomy2 stroka = '%s' % '|'.join(stroka)+'|\n' output.write(stroka) #print ("Обработано строк: "+str(i+1)) output.close()
Офлайн
Во первых, попробуйте без readlines:
for i, g in enumerate(f):
urls = defaultdict(lambda: {'sid': set(), 'pid': set()}) with open('proba.csv', 'r') as input_file: for k, s in enumerate(input_file): sid, url, pid = s.split(' | ') sid = sid.strip() url = url.strip() pid = pid.strip() selected = urls[url] selected['sid'].add(sid) selected['pid'].add(pid) if k % 65536 == 0: print('Processing line {}'.format(k)) with open('result.csv', 'w') as outfile: for u, data in urls.items(): outfile.write(' | '.join((','.join(data['sid']), u, ','.join(data['pid']))) + '\n')
Отредактировано Andrew_Lvov (Авг. 21, 2014 12:16:28)
Офлайн
Вам бы создать структуру дополнительную для хранения найденных ссылок, куда будете долепливать совпадения, таким образом, вам нужно будет пройтись по всему лишь единожды. Как ещё оптимизировать - пока что хз
Офлайн
Для таких ситуаций существует Pandas.
import pandas as pd with open('bigdata.csv') as csv: raw_data = csv.read() data = map(lambda x: x.split('|'), raw_data.split('\n')) table = pd.DataFrame(data) result = table.groupby(1).sum() result.to_csv(path_or_buf='result.csv', sep='|' )
Офлайн
Спасибо огромное за советы! Очень помогли!
Офлайн