2016-06-03 1 views
2

Я пытаюсь получить подсчет частот для слов, встречающихся в нескольких файлах в каталоге, и благодаря этому ответу here Мне удалось получить результаты, когда это слово произошло. Тем не менее, я не могу понять, как также получить результаты для отображения, когда есть 0 вхождений слова.Как получить частоту слов с помощью коллекций. Качать, даже если счет равен нулю?

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

21, 23, 60 4, 0, 8

Вот мой текущий код:

import csv 
import copy 
import os 
import sys 
import glob 
import string 
import fileinput 
from collections import Counter 

def word_frequency(fileobj, words): 
    """Build a Counter of specified words in fileobj""" 
    # initialise the counter to 0 for each word 
    ct = Counter(dict((w, 0) for w in words)) 
    file_words = (word for line in fileobj for word in line.split()) 
    filtered_words = (word for word in file_words if word in words) 
    return Counter(filtered_words) 


def count_words_in_dir(dirpath, words, action): 
    """For each .txt file in a dir, count the specified words""" 
     for filepath in glob.iglob(os.path.join(dirpath, '*.txt_out')): 
      filepath = {} 
     with open(filepath) as f: 
      ct = word_frequency(f, words) 
      action(filepath, ct) 


def final_summary(filepath, ct): 
    words = sorted(ct.keys()) 
    counts = [str(ct[k]) for k in words] 
    with open('new.csv','a') as f: 
     [f.write('{0},{1}\n,{2}\n'.format(
      filepath, 
     ', '.join(words), 
     ', '.join(counts)))] 


words = set(['21','23','60','75','79','86','107','121','147','193','194','197','198','199','200','201','229','241','263','267','309','328']) 
count_words_in_dir('C:\\Users\jllevent\Documents\PE Submsissions\Post-CLI', words, action=final_summary) 
+0

некоторые дополнительные замечания: вы можете сохранить некоторую работу инициализации 'ct' позволяя' ДИКТ .fromkey выполните эту работу для вас: 'ct = Counter (dict.fromkeys (words, 0))'. И вы можете направить больше работы на С-слой другими способами, используя встроенные функции с встроенными функциями C, например. 'file_words = itertools.chain.from_iterable (map (str.split, fileobj))' и 'filter_words = filter (frozenset (words) .__ contains__, file_words)', за которым следует 'Counter.update (filter_words)' (хотя 'Counter .update' реализован в Python, тяжелый подъем в современном Python выполняется с помощью C ускоренных 'collections._count_elements'). – ShadowRanger

+0

Примечание: 'map' и' filter' должны быть версиями Python 3, чтобы получить лучшую производительность без больших расточительных временных объектов; в Python 2 вы можете сделать «from future_builtins import map, filter», чтобы получить версии этих функций на основе генераторов. Кроме того, если вы используете Python 2.7/3.1 или более позднюю версию, вы можете использовать литералы 'set' вместо литералиста' list', завернутого в конструктор 'set':' word = {'21', '23', '60' , '75' , '79', '86', '107', '121', '147', '193', '194', '197', '198', '199', '200',» 201 ',' 229 ',' 241 ',' 263 ',' 267 ',' 309 ',' 328 '} ' – ShadowRanger

ответ

1

Вы никогда не используете счетчик ct, который вы построили в word_frequency, но создаете новый счетчик, который имеет только существующие слова , вы должны использовать ваш построены ct, например:

... 
for word in file_words: 
    if word in words: 
     ct[word] += 1 
return ct 

Или как указал @ShadowRanger ниже:

ct.update(word for word in file_words if word in words) 
return ct 
+0

Это сделало работу! Большое спасибо :) –

+1

'Counter' имеет метод' update', который упростит это (и ускорит это) значительно: 'ct.update (слово в слово в file_words, если слово в словах)'. – ShadowRanger

-1

Похоже, что возвращается NULL, если слово не появляется. Поместите в условный оператор возврата, где, если возвращаемое значение не является int> 0, верните 0.

Смежные вопросы