【发布时间】:2016-06-05 09:28:46
【问题描述】:
我正在尝试获取目录中多个文件中出现的单词频率的计数,并且感谢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)
【问题讨论】:
-
一些附加说明:您可以通过让
dict.fromkeys为您完成工作来节省一些初始化ct的工作:ct = Counter(dict.fromkeys(words, 0))。您可以通过使用带有 C 内置函数的内置函数以其他方式将更多工作推送到 C 层,例如file_words = itertools.chain.from_iterable(map(str.split, fileobj))和filtered_words = filter(frozenset(words).__contains__, file_words),然后是Counter.update(filtered_words)(虽然Counter.update是用 Python 实现的,但现代 Python 中的繁重工作是由 C 加速的collections._count_elements完成的)。 -
注意:
map和filter应该是 Python 3 版本,以在没有大量浪费临时对象的情况下获得最佳性能;在 Python 2 中,您可以使用from future_builtins import map, filter来获取这些函数的基于生成器的版本。此外,如果您使用的是 Python 2.7/3.1 或更高版本,则可以使用set文字而不是包装在set构造函数中的list文字:word = {'21','23','60','75','79','86','107','121','147','193','194','197','198','199','200','201','229','241','263','267','309','328'}