5

大量のテキスト内で最も一般的でない単語の順序付きリストを生成したいと思います。最も一般的でない単語が最初に表示され、値はテキストに表示される回数を示します。

私はいくつかのオンラインジャーナル記事からテキストを削り取り、それから単に割り当てて分割しました。

article_one = """ large body of text """.split() 
=> ("large","body", "of", "text")

正規表現は次のステップに適しているようですが、プログラミングに慣れていないので、私はあまり精通していません-最良の答えに正規表現が含まれている場合、誰かがpydoc以外の優れた正規表現チュートリアルを教えてもらえますか?

4

5 に答える 5

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])
于 2013-01-31T01:42:21.190 に答える
3

リスト内で最も一般的でない要素を検索します。コレクションモジュールのCounterクラスによると

c.most_common()[:-n-1:-1]       # n least common elements

したがって、リスト内の最も一般的でない要素のコードは

from collections import Counter
Counter( mylist ).most_common()[:-2:-1]

最も一般的でない2つの要素は

from collections import Counter
Counter( mylist ).most_common()[:-3:-1]

于 2014-05-08T15:07:23.407 に答える
1

これは少し異なるアプローチを使用しますが、ニーズに合っているようです。この回答のコードを使用します。

#!/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

printPython> = 2.4で動作し、下部のステートメントを括弧で囲んで。に変更iteritemsするとPython3+で動作しますitems

于 2013-01-31T01:40:08.553 に答える
0

固定数の最も一般的でない単語、たとえば10の最も一般的でない単語が必要な場合は、sotapmeの回答(WoLpHの提案付き)またはWoLpHの回答で提案されているように、カウンターdictとaを使用した解決策が必要になる可能性があります。heapq

wordcounter = collections.Counter(article_one)
leastcommon = word counter.nsmallest(10)

ただし、無制限の数が必要な場合、たとえば、出現回数が5回未満のすべての単語(1回の実行で6回、次の実行で69105回)が必要な場合は、リストを並べ替えた方がよい場合があります。

wordcounter = collections.Counter(article_one)
allwords = sorted(wordcounter.items(), key=operator.itemgetter(1))
leastcommon = itertools.takewhile(lambda x: x[1] < 5, allwords)

並べ替えはヒープ化よりも時間がかかりますが、最初のM要素の抽出は。listよりもはるかに高速heapです。アルゴリズム的には、違いはほんの一部のlog N要因であるため、ここでは定数が重要になります。したがって、最善の方法はテストです。

私のコードをcat reut2* >reut2.sgmpastebinで取得し、ロイター-21578コーパスで実行しただけのファイル(テキストを抽出するために処理せずに、これは明らかに深刻な作業にはあまり適していませんが、ベンチマークには問題ないはずです。 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の周り、余分なものを使って楽観的なバッチをポップして破棄する、適切な場所に並べ替える、代わりにdecorate-sort-undecorateキーなどの代わりに)、しかしそれらのどれも5%以上の改善をしませんでした(そしていくつかは物事を著しく遅くしました)。yieldnsmallestlistpartiallambda

とにかく、これらは私が予想していたよりも近いので、私はおそらくどちらかがより単純で読みやすい方を選ぶでしょう。しかし、ソートはそこでもヒープを打ち負かすと思うので…</ p>

繰り返しになりますが、最も一般的でないNが必要な場合は、妥当なNで、ヒープ実装が勝つことをテストすることなく賭けてもかまいません。

于 2013-01-31T02:52:07.463 に答える
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

于 2013-01-31T01:34:37.220 に答える