Python: подсчет уникальных слов в нескольких строках - PullRequest
0 голосов
/ 30 сентября 2011

У меня есть текстовый файл с несколькими наблюдениями. Каждое наблюдение в одной строке. Я хотел бы обнаружить уникальное вхождение каждого слова в строке. Другими словами, если одно и то же слово встречается дважды или более в одной строке, оно все равно считается как один раз. Однако я хотел бы посчитать частоту встречаемости каждого слова во всех наблюдениях. Это означает, что если слово встречается в двух или более строках, я хотел бы подсчитать количество строк, в которых оно встречалось. Вот программа, которую я написал, и она обрабатывает большое количество файлов очень медленно. Я также удаляю определенные слова в файле, ссылаясь на другой файл. Пожалуйста, предложите предложения о том, как улучшить скорость. Спасибо.

import re, string
from itertools import chain, tee, izip
from collections import defaultdict

def count_words(in_file="",del_file="",out_file=""):

    d_list = re.split('\n', file(del_file).read().lower())
    d_list = [x.strip(' ') for x in d_list] 

    dict2={}
    f1 = open(in_file,'r')
    lines = map(string.strip,map(str.lower,f1.readlines()))

    for line in lines:
        dict1={}
        new_list = []
        for char in line:
            new_list.append(re.sub(r'[0-9#$?*_><@\(\)&;:,.!-+%=\[\]\-\/\^]', "_", char))
        s=''.join(new_list)
        for word in d_list:
            s = s.replace(word,"")
        for word in s.split():
            try:
                dict1[word]=1
            except:
                dict1[word]=1
        for word in dict1.keys():
            try:
                dict2[word] += 1
            except:
                dict2[word] = 1
    freq_list = dict2.items()
    freq_list.sort()
    f1.close()

    word_count_handle = open(out_file,'w+')
    for word, freq  in freq_list:
        print>>word_count_handle,word, freq
    word_count_handle.close()
    return dict2

 dict = count_words("in_file.txt","delete_words.txt","out_file.txt")

Ответы [ 3 ]

1 голос
/ 30 сентября 2011

Не проверив производительности, на ум приходит следующее:

1) вы используете регулярные выражения - почему?Вы просто пытаетесь избавиться от определенных символов?

2) вы используете исключения для управления потоком - хотя это может быть пифоническим (лучше просить прощения, чем разрешения), бросаяисключения могут быть медленными.Как видно здесь:

    for word in dict1.keys():
        try:
            dict2[word] += 1
        except:
            dict2[word] = 1

3) превратить d_list в набор и использовать python's in для проверки членства и одновременно ...

4) избегайте интенсивного использования метода replace для строк - я полагаю, вы используете это для фильтрации слов, которые появляются в d_list.Вместо этого это можно сделать, избегая replace и просто фильтруя слова в строке, либо с использованием списка:

[word for word words if not word in del_words]

или с помощью фильтра (не очень питонического):

filter(lambda word: not word in del_words, words)
1 голос
/ 30 сентября 2011

Вы запускаете re.sub для каждого символа строки, по одному за раз. Это медленно. Сделайте это на всей линии:

s = re.sub(r'[0-9#$?*_><@\(\)&;:,.!-+%=\[\]\-\/\^]', "_", line)

Также обратите внимание на наборы и класс Counter в модуле коллекций. Это может быть быстрее, если вы просто посчитаете, а затем выбросите те, которые вам не нужны.

0 голосов
/ 30 сентября 2011
import re

u_words        = set()
u_words_in_lns = []
wordcount      = {}
words          = []

# get unique words per line
for line in buff.split('\n'):
    u_words_in_lns.append(set(line.split(' ')))

# create a set of all unique words
map( u_words.update, u_words_in_lns )

# flatten the sets into a single list of words again
map( words.extend, u_words_in_lns)

# count everything up
for word in u_words:
    wordcount[word] = len(re.findall(word,str(words)))
...