2010-11-03 27 views
27

Tôi phải đếm tần suất từ ​​trong một văn bản bằng cách sử dụng python. Tôi đã nghĩ đến việc giữ các từ trong một từ điển và có một số đếm cho mỗi từ này.Số lượng từ được sắp xếp bằng cách sử dụng python

Bây giờ, nếu tôi phải sắp xếp các từ theo # lần xuất hiện. Tôi có thể làm điều đó với cùng một từ điển thay vì sử dụng một từ điển mới có khóa là số đếm và mảng của các từ như các giá trị?

+0

bản sao có thể có của [Python: Sắp xếp từ điển theo giá trị] (http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value) –

Trả lời

20

Bạn có thể sử dụng từ điển cùng:

>>> d = { "foo": 4, "bar": 2, "quux": 3 } 
>>> sorted(d.items(), key=lambda item: item[1]) 

dòng in thứ hai:

[('bar', 2), ('quux', 3), ('foo', 4)] 

Nếu bạn chỉ muốn có một danh sách từ được sắp xếp, làm:

>>> [pair[0] for pair in sorted(d.items(), key=lambda item: item[1])] 

Đó là dòng in:

['bar', 'quux', 'foo'] 
+0

nếu các giá trị bằng nhau thì sao? Nếu các giá trị bằng nhau, có cách nào để sắp xếp chúng theo chiều dài thay thế không? – RoadRunner

+0

Giống như nếu "bar" và "quux" có số lượng bằng nhau là 3, có cách nào để làm "quux" đến trước "thanh" không? – RoadRunner

+0

Đối với tùy chọn thứ hai, bạn chỉ có thể sử dụng 'được sắp xếp (d.keys(), key = lambda item: d [item])'. – Peter

51

CẢNH BÁO: Ví dụ này yêu cầu Python 2.7 trở lên.

Tích hợp sẵn đối tượng Counter của Python chính xác là những gì bạn đang tìm kiếm. Đếm từ là ngay cả những ví dụ đầu tiên trong tài liệu:

>>> # Tally occurrences of words in a list 
>>> from collections import Counter 
>>> cnt = Counter() 
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']: 
...  cnt[word] += 1 
>>> cnt 
Counter({'blue': 3, 'red': 2, 'green': 1}) 

Như quy định trong các ý kiến, Counter mất một iterable, vì vậy ví dụ trên chỉ là để minh hoạ và tương đương với:

>>> mywords = ['red', 'blue', 'red', 'green', 'blue', 'blue'] 
>>> cnt = Counter(mywords) 
>>> cnt 
Counter({'blue': 3, 'red': 2, 'green': 1}) 
+3

Cẩn thận, 'Bộ đếm' chỉ được hỗ trợ trong Python 2.7 trở lên. –

+7

Bạn có thể muốn thêm 'từ bộ sưu tập nhập khẩu Counter' trước khi tất cả điều này :) –

+0

@Tim - ý tưởng tốt (mặc dù tôi chỉ sao chép trực tiếp từ tài liệu). – jathanism

3
>>> d = {'a': 3, 'b': 1, 'c': 2, 'd': 5, 'e': 0} 
>>> l = d.items() 
>>> l.sort(key = lambda item: item[1]) 
>>> l 
[('e', 0), ('b', 1), ('c', 2), ('a', 3), ('d', 5)] 
+0

Điều này sẽ có thêm một danh sách các bộ dữ liệu. Vì vậy, đó là một datastructure thêm phải không? – AlgoMan

+0

Có, danh sách là phụ, nhưng các bộ dữ liệu có thể được loại bỏ nếu bạn chỉ muốn từ hoặc đếm. Ngoài ra, bạn có thể sẽ cần phải sử dụng một danh sách sau khi xây dựng anyways từ điển thứ hai, vì vậy nó tạo ra một cấu trúc ít cần thiết hơn. – user470379

1

Không biết đã có một đối tượng Counter cho một nhiệm vụ như vậy. Đây là cách tôi đã làm nó trở lại sau đó, tương tự như cách tiếp cận của bạn. Bạn có thể làm việc sắp xếp trên một đại diện của cùng một từ điển.

#Takes a list and returns a descending sorted dict of words and their counts 
def countWords(a_list): 
    words = {} 
    for i in range(len(a_list)): 
     item = a_list[i] 
     count = a_list.count(item) 
     words[item] = count 
    return sorted(words.items(), key = lambda item: item[1], reverse=True) 

Một ví dụ:

>>>countWords("the quick red fox jumped over the lazy brown dog".split()) 
[('the', 2), ('brown', 1), ('lazy', 1), ('jumped', 1), ('over', 1), ('fox', 1), ('dog', 1), ('quick', 1), ('red', 1)] 
4

Bạn có thể sử dụng Counterdefaultdict trong collections mô-đun Python 2.7 trong một quá trình gồm hai bước. Lần đầu tiên sử dụng Counter để tạo từ điển trong đó mỗi từ là một khóa có số lượng tần số liên quan. Điều này khá tầm thường.

Thứ hai defaultdict có thể được sử dụng để tạo từ điển ngược hoặc đảo ngược trong đó khóa là tần suất xuất hiện và giá trị được liên kết là danh sách từ hoặc từ đã gặp phải nhiều lần. Đây là những gì tôi muốn nói:

from collections import Counter, defaultdict 

wordlist = ['red', 'yellow', 'blue', 'red', 'green', 'blue', 'blue', 'yellow'] 

# invert a temporary Counter(wordlist) dictionary so keys are 
# frequency of occurrence and values are lists the words encountered 
freqword = defaultdict(list) 
for word, freq in Counter(wordlist).items(): 
    freqword[freq].append(word) 

# print in order of occurrence (with sorted list of words) 
for freq in sorted(freqword): 
    print('count {}: {}'.format(freq, sorted(freqword[freq]))) 

Output:

count 1: ['green'] 
count 2: ['red', 'yellow'] 
count 3: ['blue'] 
2

Tôi vừa viết một chương trình tương tự, với sự giúp đỡ của Stack Overflow guys:

from string import punctuation 
from operator import itemgetter 

N = 100 
words = {} 

words_gen = (word.strip(punctuation).lower() for line in open("poi_run.txt") 
              for word in line.split()) 

for word in words_gen: 
    words[word] = words.get(word, 0) + 1 

top_words = sorted(words.items(), key=itemgetter(1), reverse=True)[:N] 

for word, frequency in top_words: 
    print ("%s %d" % (word, frequency)) 
2

Để tìm tần số của những các mặt hàng của nó dễ dàng hơn sau đó các bạn đang làm cho nó.nếu bạn có tất cả các từ trong một danh sách (rất dễ sử dụng chức năng tách chuỗi). Sau đó:

#(Pseudo Python Code) 

listOfWords = inputString.split() # splits the words up from whitespace 
setOfWords = Set(listOfWords) # Gives you all the unique words (no duplicates) 

for each word in setOfWords #Count how many words are in the list 
    print word + " appears: " + listOfWords.Count(word) + "times" 
1

Tôi đã viết một chương trình tương tự vài ngày trước. Chương trình sử dụng hai tham số: tên tập tin (bắt buộc) và N (không bắt buộc)

from collections import Counter 
import re 
import sys 

if sys.version_info <(2,7): 
    Sys.exit("Must use Python 2.7 or greater") 

if len(sys.argv)<2: 
    sys.exit('Usage: python %s filename N'%sys.argv[0]) 

n=0 
if len(sys.argv)>2: 
    try: 
     n=int(sys.argv[2]) 
     if n<=0: 
      raise ValueError 
    except ValueError: 
     sys.exit("Invalid value for N: %s.\nN must be an integer greater than 0"%sys.argv[2]) 

filename=sys.argv[1] 
try: 
     with open(filename,"r") as input_text: 
      wordcounter=Counter() 
      for line in input_text: 
       wordcounter.update(re.findall("\w+",line.lower())) 
     if n==0: 
      n=len(wordcounter) 

     for word, frequency in wordcounter.most_common(n): 
      print("%s %d" % (word, frequency)) 

except IOError: 
     sys.exit("Cannot open file: %s"% filename) 
3

Nếu bạn đang đi để yêu cầu xử lý văn bản bổ sung, nó có thể có giá trị nhập khẩu nltk (Natural Language Toolkit) vào dự án của bạn. Dưới đây là ví dụ, sử dụng bài phát biểu nhậm chức của JFK:

import nltk 

speech_text = "Vice President Johnson, Mr. Speaker, Mr. Chief Justice, President Eisenhower, Vice President Nixon, President Truman, reverend clergy, fellow citizens: We observe today not a victory of party, but a celebration of freedom — symbolizing an end, as well as a beginning — signifying renewal, as well as change. For I have sworn before you and Almighty God the same solemn oath our forebears prescribed nearly a century and three-quarters ago. The world is very different now. For man holds in his mortal hands the power to abolish all forms of human poverty and all forms of human life. And yet the same revolutionary beliefs for which our forebears fought are still at issue around the globe — the belief that the rights of man come not from the generosity of the state, but from the hand of God. We dare not forget today that we are the heirs of that first revolution. Let the word go forth from this time and place, to friend and foe alike, that the torch has been passed to a new generation of Americans — born in this century, tempered by war, disciplined by a hard and bitter peace, proud of our ancient heritage, and unwilling to witness or permit the slow undoing of those human rights to which this nation has always been committed, and to which we are committed today at home and around the world. Let every nation know, whether it wishes us well or ill, that we shall pay any price, bear any burden, meet any hardship, support any friend, oppose any foe, to assure the survival and the success of liberty. This much we pledge — and more. To those old allies whose cultural and spiritual origins we share, we pledge the loyalty of faithful friends. United there is little we cannot do in a host of cooperative ventures. Divided there is little we can do — for we dare not meet a powerful challenge at odds and split asunder. To those new states whom we welcome to the ranks of the free, we pledge our word that one form of colonial control shall not have passed away merely to be replaced by a far more iron tyranny. We shall not always expect to find them supporting our view. But we shall always hope to find them strongly supporting their own freedom — and to remember that, in the past, those who foolishly sought power by riding the back of the tiger ended up inside. To those people in the huts and villages of half the globe struggling to break the bonds of mass misery, we pledge our best efforts to help them help themselves, for whatever period is required — not because the Communists may be doing it, not because we seek their votes, but because it is right. If a free society cannot help the many who are poor, it cannot save the few who are rich. To our sister republics south of our border, we offer a special pledge: to convert our good words into good deeds, in a new alliance for progress, to assist free men and free governments in casting off the chains of poverty. But this peaceful revolution of hope cannot become the prey of hostile powers. Let all our neighbors know that we shall join with them to oppose aggression or subversion anywhere in the Americas. And let every other power know that this hemisphere intends to remain the master of its own house. To that world assembly of sovereign states, the United Nations, our last best hope in an age where the instruments of war have far outpaced the instruments of peace, we renew our pledge of support — to prevent it from becoming merely a forum for invective, to strengthen its shield of the new and the weak, and to enlarge the area in which its writ may run. Finally, to those nations who would make themselves our adversary, we offer not a pledge but a request: that both sides begin anew the quest for peace, before the dark powers of destruction unleashed by science engulf all humanity in planned or accidental self-destruction. We dare not tempt them with weakness. For only when our arms are sufficient beyond doubt can we be certain beyond doubt that they will never be employed. But neither can two great and powerful groups of nations take comfort from our present course — both sides overburdened by the cost of modern weapons, both rightly alarmed by the steady spread of the deadly atom, yet both racing to alter that uncertain balance of terror that stays the hand of mankind’s final war. So let us begin anew — remembering on both sides that civility is not a sign of weakness, and sincerity is always subject to proof. Let us never negotiate out of fear, but let us never fear to negotiate. Let both sides explore what problems unite us instead of belaboring those problems which divide us. Let both sides, for the first time, formulate serious and precise proposals for the inspection and control of arms, and bring the absolute power to destroy other nations under the absolute control of all nations. Let both sides seek to invoke the wonders of science instead of its terrors. Together let us explore the stars, conquer the deserts, eradicate disease, tap the ocean depths, and encourage the arts and commerce. Let both sides unite to heed, in all corners of the earth, the command of Isaiah — to “undo the heavy burdens, and [to] let the oppressed go free.”¹ And, if a beachhead of cooperation may push back the jungle of suspicion, let both sides join in creating a new endeavor — not a new balance of power, but a new world of law — where the strong are just, and the weak secure, and the peace preserved. All this will not be finished in the first one hundred days. Nor will it be finished in the first one thousand days; nor in the life of this Administration; nor even perhaps in our lifetime on this planet. But let us begin. In your hands, my fellow citizens, more than mine, will rest the final success or failure of our course. Since this country was founded, each generation of Americans has been summoned to give testimony to its national loyalty. The graves of young Americans who answered the call to service surround the globe. Now the trumpet summons us again — not as a call to bear arms, though arms we need — not as a call to battle, though embattled we are — but a call to bear the burden of a long twilight struggle, year in and year out, “rejoicing in hope; patient in tribulation,”² a struggle against the common enemies of man: tyranny, poverty, disease, and war itself. Can we forge against these enemies a grand and global alliance, North and South, East and West, that can assure a more fruitful life for all mankind? Will you join in that historic effort? In the long history of the world, only a few generations have been granted the role of defending freedom in its hour of maximum danger. I do not shrink from this responsibility — I welcome it. I do not believe that any of us would exchange places with any other people or any other generation. The energy, the faith, the devotion which we bring to this endeavor will light our country and all who serve it. And the glow from that fire can truly light the world. And so, my fellow Americans, ask not what your country can do for you; ask what you can do for your country. My fellow citizens of the world, ask not what America will do for you, but what together we can do for the freedom of man. Finally, whether you are citizens of America or citizens of the world, ask of us here the same high standards of strength and sacrifice which we ask of you. With a good conscience our only sure reward, with history the final judge of our deeds, let us go forth to lead the land we love, asking His blessing and His help, but knowing that here on earth God’s work must truly be our own." 

# Tokenize the words 
all_words = speech_text.lower().split() 

# Create a frequency distribution 
freq = nltk.FreqDist(all_words) 

# Show the top 10 words in the list, with counts 
freq.items()[:10] 

Out[5]: 
[('the', 86), 
('of', 66), 
('to', 42), 
('and', 40), 
('we', 30), 
('a', 29), 
('in', 24), 
('our', 21), 
('not', 19), 
('that', 19)] 

# Show the top 10 keys in the frequency dictionary 
freq.keys()[:10] 

Out[6]: ['the', 'of', 'to', 'and', 'we', 'a', 'in', 'our', 'not', 'that'] 

# Those frequent words aren't very interesting... let's strip common words 
from nltk.corpus import stopwords 

stop_words = set(stopwords.words('english')) 
clean_words = [w for w in all_words if not w in stop_words] 
freq_clean = nltk.FreqDist(clean_words) 

# This is a little more interesting 
freq_clean.items()[1:10] 
[('let', 16), 
('us', 11), 
('new', 7), 
('sides', 7), 
('pledge', 6), 
('ask', 5), 
('shall', 5), 
('always', 4), 
('call', 4)] 

NLTK sẽ cho phép bạn thực hiện mọi cách phân tích thú vị khác với văn bản nếu cần. Dưới đây là một ví dụ nhanh về cách bạn sẽ tìm ra 10 bigrams đầu xảy ra hơn 3 lần trong văn bản:

bigram_measures = nltk.collocations.BigramAssocMeasures() 
bigram_finder = nltk.collocations.BigramCollocationFinder.from_words(all_words) 
bigram_finder.apply_freq_filter(3) 
bigram_finder.nbest(bigram_measures.pmi, 10) 

Out[28]: 
[('my', 'fellow'), 
('both', 'sides'), 
('can', 'do'), 
('dare', 'not'), 
('let', 'us'), 
('we', 'dare'), 
('do', 'for'), 
('let', 'both'), 
('we', 'shall'), 
('a', 'call')] 

Tham khảo NLTK Documentation để biết thêm thông tin và ví dụ về làm thế nào để, ví dụ, một cách nhanh chóng tạo ra một âm mưu các cụm từ thường xuyên nhất trong văn bản của bạn.

Các vấn đề liên quan