ann*_*e_t 5 python counter word-frequency
我正在对文本进行文本分析,由于PDF到txt的转换错误,有时会把单词混在一起。因此,我想匹配字符串,而不是匹配单词。
例如,我有字符串:
mystring='The lossof our income made us go into debt but this is not too bad as we like some debts.'
Run Code Online (Sandbox Code Playgroud)
我寻找
key_words=['loss', 'debt', 'debts', 'elephant']
Run Code Online (Sandbox Code Playgroud)
输出应采用以下形式:
Filename Debt Debts Loss Elephant
mystring 2 1 1 0
Run Code Online (Sandbox Code Playgroud)
我所拥有的代码工作正常,除了一些小故障:1)它不报告零频单词的出现频率(因此输出中不会出现“大象”:2)key_words中单词的顺序似乎很重要(即,有时我对“债务”和“债务”各取1个计数,有时它只报告“债务”的2个计数,而“未报告债务”。如果我设法“打印”,我可以接受第二点”变量名称添加到数据集...但不确定如何操作。
以下是相关代码。谢谢!PS。不用说,它不是最优雅的代码,但是我正在慢慢学习。
bad=set(['debts', 'debt'])
csvfile=open("freq_10k_test.csv", "w", newline='', encoding='cp850', errors='replace')
writer=csv.writer(csvfile)
for filename in glob.glob('*.txt'):
with open(filename, encoding='utf-8', errors='ignore') as f:
file_name=[]
file_name.append(filename)
new_review=[f.read()]
freq_all=[]
rev=[]
from collections import Counter
for review in new_review:
review_processed=review.lower()
for p in list(punctuation):
review_processed=review_processed.replace(p,'')
pattern = re.compile("|".join(bad), flags = re.IGNORECASE)
freq_iter=collections.Counter(pattern.findall(review_processed))
frequency=[value for (key,value) in sorted(freq_iter.items())]
freq_all.append(frequency)
freq=[v for v in freq_all]
fulldata = [ [file_name[i]] + freq for i, freq in enumerate(freq)]
writer=csv.writer(open("freq_10k_test.csv",'a',newline='', encoding='cp850', errors='replace'))
writer.writerows(fulldata)
csvfile.flush()
Run Code Online (Sandbox Code Playgroud)
您可以预先初始化计数器,如下所示:
freq_iter = collections.Counter()
freq_iter.update({x:0 for x in bad})
freq_iter.update(pattern.findall(review_processed))
Run Code Online (Sandbox Code Playgroud)
一件好事Counter是您实际上不必预先初始化它 - 您可以只做c = Counter(); c['key'] += 1,但是如果您愿意,没有什么可以阻止您将某些值预先初始化为 0。
对于debt/debts事情 - 这只是一个未充分说明的问题。在这种情况下,您希望代码做什么?如果您希望它匹配匹配的最长模式,则需要对列表进行最长排序,这将解决它。如果您想同时报告两者,您可能需要进行多次搜索并保存所有结果。
更新以添加一些关于为什么找不到的信息debts:这与正则表达式 findall 的关系比其他任何事情都多。re.findall总是寻找最短的匹配项,但一旦找到,它就不会将其包含在后续匹配项中:
In [2]: re.findall('(debt|debts)', 'debtor debts my debt')
Out[2]: ['debt', 'debt', 'debt']
Run Code Online (Sandbox Code Playgroud)
如果您真的想找到每个单词的所有实例,则需要分别进行:
In [3]: re.findall('debt', 'debtor debts my debt')
Out[3]: ['debt', 'debt', 'debt']
In [4]: re.findall('debts', 'debtor debts my debt')
Out[4]: ['debts']
Run Code Online (Sandbox Code Playgroud)
但是,也许您真正要寻找的是words。在这种情况下,使用\b运算符来要求分词:
In [13]: re.findall(r'\bdebt\b', 'debtor debts my debt')
Out[13]: ['debt']
In [14]: re.findall(r'(\b(?:debt|debts)\b)', 'debtor debts my debt')
Out[14]: ['debts', 'debt']
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是你想要的或不...在这种情况下,它能够区分debt和debts正确的,但错过了debtor,因为它只匹配字符串,我们要求它不要。
根据您的用例,您可能想要研究对文本进行词干处理...我相信 nltk 中有一个非常简单(只使用过一次,所以我不会尝试发布示例...这个问题在NLTK结合文本制止和拆除标点符号和scikit学习可能是有用的),就应减少debt,debts以及debtor所有的同根词debt,并为换句话说做类似的事情。这可能有帮助,也可能没有帮助;我不知道你用它做什么。
| 归档时间: |
|
| 查看次数: |
983 次 |
| 最近记录: |