我有一个包含多个观察结果的文本文件。每次观察都在一行中。我想检测一行中每个单词的唯一出现。换句话说,如果同一个单词在同一行上出现两次或更多次,它仍然被计为一次。但是,我想计算所有观察中每个单词出现的频率。这意味着如果一个单词出现在两行或更多行中,我想计算它出现的行数。这是我编写的程序,它在处理大量文件时非常慢。我还通过引用另一个文件删除文件中的某些单词。请提供有关如何提高速度的建议。谢谢。
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")
答案 0 :(得分:1)
您正在线路的每个字符上运行re.sub,一次一个。那很慢。全程做到:
s = re.sub(r'[0-9#$?*_><@\(\)&;:,.!-+%=\[\]\-\/\^]', "_", line)
另外,查看集合模块中的集合和Counter类。如果你只计算然后丢弃那些你不想要的东西,它可能会更快。
答案 1 :(得分:1)
在没有进行任何性能测试的情况下,我想到了以下内容:
1)你正在使用正则表达式 - 为什么?你只是想摆脱某些角色吗?
2)你正在使用流控制的异常 - 尽管它可以是pythonic(更好地请求宽恕而不是权限),抛出异常通常很慢。如下所示:
for word in dict1.keys():
try:
dict2[word] += 1
except:
dict2[word] = 1
3)将d_list
转换为一个集合,并使用python的in
来测试成员资格,同时...
4)避免在字符串上大量使用replace
方法 - 我相信您正在使用它来过滤掉d_list
中出现的字词。这可以通过避免replace
来完成,只需过滤列中的单词,或者使用列表解析:
[word for word words if not word in del_words]
或使用过滤器(不是非常pythonic):
filter(lambda word: not word in del_words, words)
答案 2 :(得分:0)
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)))