我想在大量文本中生成最不常见单词的有序列表,首先出现最不常见的单词以及表示它在文本中出现的次数的值。
我从一些在线期刊文章中删除了文本,然后简单地分配和分割;
article_one = """ large body of text """.split()
=> ("large","body", "of", "text")
看起来像正则表达式适合接下来的步骤,但对编程不熟悉我不太精通 - 如果最好的答案包括一个正则表达式,有人可以指向我除了pydoc之外的一个很好的正则表达式教程吗?
答案 0 :(得分:4)
如果使用defaultdict更短/更简单的版本,Counter很不错但需要Python 2.7,这适用于2.5及以上版本:)
import collections
counter = collections.defaultdict(int)
article_one = """ large body of text """
for word in article_one.split():
counter[word] += 1
print sorted(counter.iteritems(), key=lambda x: x[::-1])
答案 1 :(得分:2)
查找列表中最不常见的元素。根据{{3}}
中的Counter类c.most_common()[:-n-1:-1] # n least common elements
所以列表中最小公共元素的代码是
from collections import Counter
Counter( mylist ).most_common()[:-2:-1]
两个最不常见的元素是
from collections import Counter
Counter( mylist ).most_common()[:-3:-1]
答案 2 :(得分:1)
这采用略有不同的方法,但它似乎符合您的需求。使用this answer中的代码。
#!/usr/bin/env python
import operator
import string
article_one = """A, a b, a b c, a b c d, a b c d efg.""".split()
wordbank = {}
for word in article_one:
# Strip word of punctuation and capitalization
word = word.lower().strip(string.punctuation)
if word not in wordbank:
# Create a new dict key if necessary
wordbank[word] = 1
else:
# Otherwise, increment the existing key's value
wordbank[word] += 1
# Sort dict by value
sortedwords = sorted(wordbank.iteritems(), key=operator.itemgetter(1))
for word in sortedwords:
print word[1], word[0]
输出:
1 efg
2 d
3 c
4 b
5 a
使用Python> = 2.4和Python 3+,如果您在底部括起print
语句并将iteritems
更改为items
。
答案 3 :(得分:0)
# From the official documentation ->>
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})
## ^^^^--- from the standard documentation.
>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall('\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
>>> def least_common(adict, n=None):
.....: if n is None:
.....: return sorted(adict.iteritems(), key=itemgetter(1), reverse=False)
.....: return heapq.nsmallest(n, adict.iteritems(), key=itemgetter(1))
显然适应套房:D
答案 4 :(得分:0)
如果您需要固定数量的最不常见的单词,例如10个最不常见的单词,您可能需要使用计数器dict
和heapq
的解决方案,正如sotapme的答案(使用WoLpH的建议)或WoLpH的回答:
wordcounter = collections.Counter(article_one)
leastcommon = word counter.nsmallest(10)
但是,如果你需要一个无限数量的它们,例如,所有出现次数少于5的单词,一次运行可以是6,而下一次运行可以是69105,你可能最好只对列表进行排序:
wordcounter = collections.Counter(article_one)
allwords = sorted(wordcounter.items(), key=operator.itemgetter(1))
leastcommon = itertools.takewhile(lambda x: x[1] < 5, allwords)
排序比堆积更长,但使用list
而不是heap
,提取前M个元素的速度要快得多。从算法上讲,差异只是一些log N
因子,所以常量在这里很重要。所以最好的办法就是测试。
在我的code at pastebin语料库上执行我的Reuters-21578和一个只做cat reut2* >reut2.sgm
的文件(没有处理它来提取文本,所以这对于认真的工作显然不是很好,但对于基准测试应该没问题,因为没有一个SGML标签会最不常见......):
$ python leastwords.py reut2.sgm # Apple 2.7.2 64-bit
heap: 32.5963380337
sort: 22.9287009239
$ python3 leastwords.py reut2.sgm # python.org 3.3.0 64-bit
heap: 32.47026552911848
sort: 25.855643508024514
$ pypy leastwords.py reut2.sgm # 1.9.0/2.7.2 64-bit
heap: 23.95291996
sort: 16.1843900681
我尝试了各种方法来加速它们中的每一个(包括:takewhile
围绕genexp而不是堆版本中yield
的循环,弹出乐观批处理nsmallest
并投掷远离任何多余的东西,制作list
并进行排序,装饰 - 排序 - 不装饰而不是密钥,partial
而不是lambda
等等),但它们都没有超过5%的改进(有些使得事情明显变慢)。
无论如何,这些比我预期的更接近,所以我可能会选择更简单,更易读的。但是我觉得那里也有堆积,所以...
再一次:如果你只需要N个最不常见的,对于合理的N,我愿意打赌,甚至不测试堆实现是否会赢。