Расчет частоты слов для текстового файла объемом 1 ГБ в Python

Я пытаюсь рассчитать частоту слов для текстового файла размером 1,2 ГБ, который составляет около 203 миллионов слов. Я использую следующий код Python. Но это дает мне ошибку памяти. Есть ли какое-нибудь решение для этого?

Вот мой код:

import re
# this one in honor of 4th July, or pick text file you have!!!!!!!
filename = 'inputfile.txt'
# create list of lower case words, \s+ --> match any whitespace(s)
# you can replace file(filename).read() with given string
word_list = re.split('\s+', file(filename).read().lower())
print 'Words in text:', len(word_list)
# create dictionary of word:frequency pairs
freq_dic = {}
# punctuation marks to be removed
punctuation = re.compile(r'[.?!,":;]') 
for word in word_list:
    # remove punctuation marks
    word = punctuation.sub("", word)
    # form dictionary
    try: 
        freq_dic[word] += 1
    except: 
        freq_dic[word] = 1

print 'Unique words:', len(freq_dic)
# create list of (key, val) tuple pairs
freq_list = freq_dic.items()
# sort by key or word
freq_list.sort()
# display result
for word, freq in freq_list:
    print word, freq

И вот ошибка, которую я получил:

Traceback (most recent call last):
  File "count.py", line 6, in <module>
    word_list = re.split('\s+', file(filename).read().lower())
  File "/usr/lib/python2.7/re.py", line 167, in split
    return _compile(pattern, flags).split(string, maxsplit)
MemoryError

person Jyotiska    schedule 03.02.2013    source источник


Ответы (2)


Проблема начинается прямо здесь:

file(filename).read()

Это читает весь файл в строку. Вместо этого, если вы обрабатываете файл построчно или по частям, вы не столкнетесь с проблемой памяти.

with open(filename) as f:
    for line in f:

Вы также можете использовать collections.Counter для подсчета частотности слов.

In [1]: import collections

In [2]: freq = collections.Counter()

In [3]: line = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod'

In [4]: freq.update(line.split())

In [5]: freq
Out[5]: Counter({'ipsum': 1, 'amet,': 1, 'do': 1, 'sit': 1, 'eiusmod': 1, 'consectetur': 1, 'sed': 1, 'elit,': 1, 'dolor': 1, 'Lorem': 1, 'adipisicing': 1})

И посчитать еще несколько слов,

In [6]: freq.update(line.split())

In [7]: freq
Out[7]: Counter({'ipsum': 2, 'amet,': 2, 'do': 2, 'sit': 2, 'eiusmod': 2, 'consectetur': 2, 'sed': 2, 'elit,': 2, 'dolor': 2, 'Lorem': 2, 'adipisicing': 2})

collections.Counter является подклассом dict, поэтому вы можете использовать его способами, с которыми вы уже знакомы. Кроме того, в нем есть несколько полезных методов подсчета, таких как most_common.

person unutbu    schedule 03.02.2013

Проблема в том, что вы пытаетесь прочитать весь файл в память. Решение считывается из файла построчно, подсчитывается количество слов в каждой строке и суммируется результат.

person ChrisBlom    schedule 03.02.2013