Подсчет частоты слов в документах с использованием регулярных выражений Python - PullRequest
5 голосов
/ 23 марта 2011

Создан модуль python, который читает файл, удаляет стоп-слова и выводит словарь python со словом и его частотой (сколько раз это встречалось в документе).

def run():
filelist = os.listdir(path)
regex = re.compile(r'.*<div class="body">(.*?)</div>.*', re.DOTALL | re.IGNORECASE)
reg1 = re.compile(r'<\/?[ap][^>]*>', re.DOTALL | re.IGNORECASE)
quotereg = re.compile(r'&quot;', re.DOTALL | re.IGNORECASE)
puncreg = re.compile(r'[^\w]', re.DOTALL | re.IGNORECASE)
f = open(stopwordfile, 'r')
stopwords = f.read().lower().split()
totalfreq = {}

filewords = {}
htmlfiles = []
for file in filelist:
    if file[-5:] == '.html':
        htmlfiles.append(file)

for file in htmlfiles:
    f = open(path + file, 'r')
    words = f.read().lower()
    words = regex.findall(words)[0]
    words = quotereg.sub(' ', words)
    words = reg1.sub(' ', words)
    words = puncreg.sub(' ', words)
    words = words.strip().split()

    for w in stopwords:
        while w in words:
            words.remove(w)

     freq = {}
    for w in words:
       if w in freq:
           totalfreq[w] = totalfreq[w] + 1
           freq[w] = freq[w] + 1
       else:
           totalfreq[w] = 1
           freq[w] = 1
           filewords[file] = freq


    print totalfreq

Это печатаетвсе «нон-стоп» слова в этом файле и частота, с которой они встречаются в файле: вывод выглядит следующим образом:

{{'saturday': 1, 'irish': 1,'семья': 1, 'дать': 1, 'год': 2, 'выходные': 1, 'Стив': 1, 'гости': 1, 'вопросы': 1, 'в': 2, 'усилие': 1,' партнер ': 1,' вымирание ': 1,' платье ': 1,' дети ': 4,' утанс ': 1,' 27 ': 1,' повышение ': 1,' шкаф ':1, 'волосатый': 2, 'make': 1, 'humphreys': 1, 'родственники': 1, 'зоопарк': 5, 'подвергаемый опасности': 1, 'воскресенье': 1, 'special': 1,«ответ»: 1, «публика»: 1, «осведомленность»: 1, «запланировано»: 1, «деятельность»: 1, «риона»: 1, «орангутаны»: 4, «планы»: 1, «Леония»': 1,' orang ': 1,' вчера ': 2,' свободный ': 2,' рука ': 1,' дикий ': 1,' независимый ': 1,' часть ': 1,' подготовка ':1, «раскрыто»: 1, «день»: 1, «человек»: 1, «фотография»: 1, «кин»: 1, 'животные': 1, '14': 1, 'кевин': 1, '16': 1, '32': 1, 'возраст': 1, 'Сибу': 1, 'Дублин': 2, 'хранители: 1, «лицо»: 1, «муджур»: 1, «красный»: 2, «орангутан»: 1, «вид»: 1, «запись»: 1, «усилия»: 1, «шоу»: 1, '11:00': 1, 'приток': 1, '3:00': 1}

{'newest': 1, 'Birth': 2, 'Orang': 1, 'month':1, «Стив»: 1, «Вопросы»: 1, «Утанс»: 1, «Дети»: 4, «Персонал»: 1, «Центр внимания»: 1, «27»: 1, «на основе»: 1,«обеспокоены»: 1, «воскресенье»: 1, «3 вечера»: 1, «наконец»: 1, «4»: 1, «Мейв»: 1, «осведомленность»: 1, «дал»: 1, «деятельность»': 1,' жираф ': 1,' facebook ': 1,' подготовка ': 1,' фон ': 1,' воспитание ': 1,' день ': 1,' дебют ': 1,' rothschild ':1, «хранители»: 1, «электронная почта»: 1, «шаги»: 1, «11:00»: 1, «страница»: 1, «фотография»: 1, «родился»: 1, «результат»: 1,'year': 2, 'суббота': 1, 'special': 1, 'шкаф': 1, 'haired': 2, 'section': 1, 'bennet': 2, 'mum': 3, 'mujur': 1,' условия ': 1,' общедоступный ': 1,' красный ': 2,' показывает ': 1,' орангутаны ': 4,' свободный ': 2,' хранитель ': 1,' ноябрь ':1, «забота»: 1, «отправка»: 1, «великий»: 1, «ori»Джинс: 1, «32»: 1, «приглашен»: 1, «Дублин»: 2, «запланирован»: 1, «орангутан»: 1, «усилия»: 1, «приток»: 1, «назван»: 1, «семья»: 1, «восхищение»: 1, «погода»: 1, «гости»: 1, «вымирание»: 1, «публика»: 1, «впечатление»: 1, «повышение»: 1, «раскрыто»: 1, «осталось»: 1, «хамфрис»: 1, «уверенно»: 1, «теленок»: 3, «вход»: 1, «шейн»: 1, «часть»: 1, «helen ': 1,' внимательный ': 1,' усилие ': 1,' case ': 1,' made ': 2,' animals ': 1,' 14 ': 1,' 16 ': 1,' ms ': 1, «дикий»: 1, «саванна»: 1, «ирландский»: 1, «дать»: 1, «резидент»: 1, «предложения»: 1, «промах»: 1, «в»: 2, «партнер»: 1, «платье»: 1, «вид»: 1, «кевин»: 1, «риона»: 1, «make»: 1, «зоопарк»: 3, «вымирающий»: 1, «родственники ': 1,' ответ ': 1,' бедные ': 1,' независимые ': 1,' планы ': 1,' leonie ': 1,' время ': 1,' вчера ': 1,' рука ': 1, «хикки»: 1, «выходные»: 1, «человек»: 1, «Сибу»: 1, «возраст»: 1, «устойчивый»: 2, «лицо»: 1, «заключение»: 1, 'african': 2, 'entry': 1, 'keane': 1, 'clarke': 2, 'left': 1}

Но мне нужно сложить обе суммы изботh файлов или большое количество файлов, чтобы дать общее количество слов, например, "zoo" во всех файлах.1-й файл zoo = 5 2-й файл zoo = 3 всего = 8.

Не получается понять, как я считаю слова для многих файлов, а не только для одного за раз.

Есть идеи?!

Ответы [ 4 ]

2 голосов
/ 23 марта 2011

Обратная косая черта в '<\/?[ap][^>]*>' бесполезна, поскольку '/' не является специальным символом

'[^\w]' означает '\W' Кстати, '[^\w]+' будет более эффективным, чем один '[^\w]'

re.DOTALL бесполезен с r'<\/?[ap][^>]*>', так как в этом RE нет точки

Если вы сделаете words = f.read().lower(), чтобы уменьшить буквы, вы ненужно re.IGNORECASE

RE для замены могут быть помещены в один RE: reg123 = re.compile(r'(</?[ap][^>]*>|&quot;|\W+)')

file не подходит для имени файлаname, оно переопределяет имя существующей встроенной функции

, заменяя строки кода для получения htmfiles выражением генератора лучше

Я не понимаюпочему '[0]' в words = regex.findall(words)[0]

Вы также можете сгруппировать слова стоп-слов в RE, которые используются для замены на ' ':

stopwords = '|'.join(f.read().lower().split())

для включения в REдля замены

отступ в filewords[file] = freq плохой

.

Предлагаю вам следующее улучшение;Я не проверял это, потому что я не файлы для обработки.Это конечно не идеально.Спросите неясные вопросы.

def run():

    from collection import difaultdict

    with open(stopwordfile, 'r') as f:
        stopwords = '|'.join(f.read().lower().split())

    regex = re.compile(r'.*<div class="body">(.*?)</div>.*', re.DOTALL)
    reg123 = re.compile(r'(</?[ap][^>]*>|&quot;|\W+|'+stopwords+')')

    totalfreq = defaultdict(int)
    filewords = {}

    for filename in (fn for fn in os.listdir(path) if fn[-5:] == '.html'):
        with open(path + filename, 'r') as f:
            ch = regex.findall(f.read().lower())[0]
            ch = reg123.sub(' ', ch)
            words = ch.strip().split()

        freq = defaultdict(int)
        for w in words:
            totalfreq[w] += 1
            freq[w] += 1
        filewords[filename] = freq

    print totalfreq

Я не очень хорошо понял ваш вопрос.Пожалуйста, дайте точность

2 голосов
/ 23 марта 2011

Модуль fileinput позволяет легко обрабатывать несколько файлов.

0 голосов
/ 23 марта 2011

при условии, что files - это список частот для каждого вашего файла, попробуйте что-то вроде:

from itertools import groupby, chain
total = dict(
              (key, sum(c[1] for c in vals))
              for key, vals in 
              groupby(
                  sorted(
                      chain(
                          *(f.items() for f in files)
                      )
                  ), 
                  lambda x: x[0]
              )
            )
0 голосов
/ 23 марта 2011

Возможное решение:

result = {}
for d in dictionaries:
  for k,v in d.iteritems():
    result[k] = result.get(k,0) + v

for k,v in result.iteritems():
  print('total occurences of {0}: {1}'.format(k,v))

... где dictionaries - это просто список преобразований частоты в слова для каждого из входных файлов.

...