Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 21, 2014 08:29:07

Seganapa
От: Новороссийск
Зарегистрирован: 2012-07-31
Сообщения: 139
Репутация: +  0  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Всем доброго дня!
Уважаемые Питонщики, мне необходима Ваша помощь.

Имеется большой текстовый файл, размером 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 штук.
Заранее СПАСИБО!



—————————————————————–
Изучаю и параллельно использую Python 2.7

Офлайн

#2 Авг. 21, 2014 09:43:45

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Seganapa
В общем моих знаний питона хватило на то, чтобы написать цикл в цикле
А написанный вами код где?
Непонятно куда вы потом данные деваете.
Непонятно что вы с файлами будете делать. Надо получить общий результат или отдельно по файлам?



Отредактировано doza_and (Авг. 21, 2014 09:45:40)

Офлайн

#3 Авг. 21, 2014 10:16:11

Seganapa
От: Новороссийск
Зарегистрирован: 2012-07-31
Сообщения: 139
Репутация: +  0  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

#!/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()

На выходе получаю файл со строками

sid0014 ,sid00235345634 | http://gagaga.com/num=0310103&id=22556756 | pid=2346786, pid=3425457785343|
sid0048 | http://gagaga.com/num=045345345&id=22553425 | pid=567456|
sid0093 | http://gagaga.com/num=126654&id=225534756 | pid=867546433|

Мне это и нужно, только ооооочень медленно работает. Как ускорить процесс?



—————————————————————–
Изучаю и параллельно использую Python 2.7

Офлайн

#4 Авг. 21, 2014 12:16:08

Andrew_Lvov
Зарегистрирован: 2013-03-05
Сообщения: 19
Репутация: +  1  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Во первых, попробуйте без readlines:

for i, g in enumerate(f):

Во вторых, вы 4 раза делаете g1.split('|'). Выносите в переменную.

3. replace('\n', '') можно, я так понимаю, заменить на strip().

4. Ой мляяя, двойной цикл…… Квадратичная сложность. 16 000 000 000 000 итераций.

    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)

Офлайн

#5 Авг. 22, 2014 12:51:41

Master_Sergius
Зарегистрирован: 2013-09-12
Сообщения: 271
Репутация: +  7  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Вам бы создать структуру дополнительную для хранения найденных ссылок, куда будете долепливать совпадения, таким образом, вам нужно будет пройтись по всему лишь единожды. Как ещё оптимизировать - пока что хз



———————————————————————————
Мой блог о семействе *nix: http://nixtravelling.blogspot.com/

Офлайн

#6 Авг. 22, 2014 21:37:04

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Для таких ситуаций существует 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='|' )

Офлайн

#7 Авг. 29, 2014 07:54:24

Seganapa
От: Новороссийск
Зарегистрирован: 2012-07-31
Сообщения: 139
Репутация: +  0  -
Профиль   Отправить e-mail  

Как увеличить скорость (оптимизировать) обработки большого файла

Спасибо огромное за советы! Очень помогли!



—————————————————————–
Изучаю и параллельно использую Python 2.7

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version