计算列表中单词的频率并按频率排序


76

我正在使用Python 3.3

我需要创建两个列表,一个用于唯一词,另一个用于词频。

我必须根据频率列表对唯一单词列表进行排序,以使频率最高的单词在列表中排在首位。

我有文本设计,但是不确定如何在Python中实现它。

到目前为止,我发现的方法都使用了Counter我们还没有学过的词典。我已经从包含所有单词的文件中创建了列表,但是不知道如何找到列表中每个单词的频率。我知道我需要循环才能执行此操作,但无法弄清楚。

这是基本设计:

 original list = ["the", "car",....]
 newlst = []
 frequency = []
 for word in the original list
       if word not in newlst:
           newlst.append(word)
           set frequency = 1
       else
           increase the frequency
 sort newlst based on frequency list 

1
我们很难知道你知道什么。你学到了set吗?count列表的方法?等。用有意义的术语来约束问题。
roippi 2013年

2
为什么不允许您使用未教过的东西?这些天是否会阻碍学习?
John La Rooy 2013年

一个特里将是一个相当有效的替代。您可以只用一个列表构建一个列表
John La Rooy 2013年

2
请考虑接受答案。
PatrickT

Answers:



48

您可以使用

from collections import Counter

它支持Python 2.7,在这里阅读更多信息

1。

>>>c = Counter('abracadabra')
>>>c.most_common(3)
[('a', 5), ('r', 2), ('b', 2)]

使用字典

>>>d={1:'one', 2:'one', 3:'two'}
>>>c = Counter(d.values())
[('one', 2), ('two', 1)]

但是,您必须先读取文件,然后转换为dict。

2.这是python docs示例,使用re和Counter

# Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\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)]

18
words = file("test.txt", "r").read().split() #read the words into a list.
uniqWords = sorted(set(words)) #remove duplicate words and sort
for word in uniqWords:
    print words.count(word), word

很棒的pythonian方式!
karlgzafiris

6
您是否使用大文件测试了代码?如果文件太大,将花费大量时间。收集效率更高。
托尼·王

这不如Counter。您在执行操作时会不必要地丢弃计数set(words),因此,每次需要计数时,都必须使用来查找计数words.count(word),这尤其会导致效率低下。用于大文本。
smci

6

在不使用集合的情况下使用另一种算法的另一种解决方案:

def countWords(A):
   dic={}
   for x in A:
       if not x in  dic:        #Python 2.7: if not dic.has_key(x):
          dic[x] = A.count(x)
   return dic

dic = countWords(['apple','egg','apple','banana','egg','apple'])
sorted_items=sorted(dic.items())   # if you want it sorted

5

熊猫回答:

import pandas as pd
original_list = ["the", "car", "is", "red", "red", "red", "yes", "it", "is", "is", "is"]
pd.Series(original_list).value_counts()

如果您想要按升序排列,则它很简单:

pd.Series(original_list).value_counts().sort_values(ascending=True)

4

一种方法是制作一个列表列表,新列表中的每个子列表都包含一个单词和一个计数:

list1 = []    #this is your original list of words
list2 = []    #this is a new list

for word in list1:
    if word in list2:
        list2.index(word)[1] += 1
    else:
        list2.append([word,0])

或者,更有效地:

for word in list1:
    try:
        list2.index(word)[1] += 1
    except:
        list2.append([word,0])

这将不如使用字典有效,但使用了更多基本概念。


4

您可以使用reduce()-一种实用的方法。

words = "apple banana apple strawberry banana lemon"
reduce( lambda d, c: d.update([(c, d.get(c,0)+1)]) or d, words.split(), {})

返回:

{'strawberry': 1, 'lemon': 1, 'apple': 2, 'banana': 2}

2

使用Counter是最好的方法,但是如果您不想这样做,则可以自己实现。

# The list you already have
word_list = ['words', ..., 'other', 'words']
# Get a set of unique words from the list
word_set = set(word_list)
# create your frequency dictionary
freq = {}
# iterate through them, once per unique word.
for word in word_set:
    freq[word] = word_list.count(word) / float(len(word_list))

freq将以列表中每个单词的出现频率结束。

您需要float在那里将整数之一转换为浮点数,因此结果值将是浮点数。

编辑:

如果您不能使用字典或集合,这是另一种效率较低的方法:

# The list you already have
word_list = ['words', ..., 'other', 'words']
unique_words = []
for word in word_list:
    if word not in unique_words:
        unique_words += [word]
word_frequencies = []
for word in unique_words:
    word_frequencies += [float(word_list.count(word)) / len(word_list)]
for i in range(len(unique_words)):
    print(unique_words[i] + ": " + word_frequencies[i])

的indiciesunique_wordsword_frequencies匹配。


1

理想的方法是使用将单词映射到其数量的字典。但是,如果您不能使用它,则可能要使用2个列表-1个存储单词,而另一个存储单词计数。请注意,此处的字数顺序很重要。实现这一点将很困难,而且效率不高。


事实证明,我必须努力工作,因此我需要两个列表。我已经存储了单词,但是不确定如何以可以基于频率列表对单词列表进行排序的方式来存储频率。
user3088605 2013年

0

试试这个:

words = []
freqs = []

for line in sorted(original list): #takes all the lines in a text and sorts them
    line = line.rstrip() #strips them of their spaces
    if line not in words: #checks to see if line is in words
        words.append(line) #if not it adds it to the end words
        freqs.append(1) #and adds 1 to the end of freqs
    else:
        index = words.index(line) #if it is it will find where in words
        freqs[index] += 1 #and use the to change add 1 to the matching index in freqs

0

这是代码支持您的问题is_char()检查是否仅对那些字符串进行验证字符串计数,Hashmap是python中的字典

def is_word(word):
   cnt =0
   for c in word:

      if 'a' <= c <='z' or 'A' <= c <= 'Z' or '0' <= c <= '9' or c == '$':
          cnt +=1
   if cnt==len(word):
      return True
  return False

def words_freq(s):
  d={}
  for i in s.split():
    if is_word(i):
        if i in d:
            d[i] +=1
        else:
            d[i] = 1
   return d

 print(words_freq('the the sky$ is blue not green'))

-2

最好的事情是:

def wordListToFreqDict(wordlist):
    wordfreq = [wordlist.count(p) for p in wordlist]
    return dict(zip(wordlist, wordfreq))

然后尝试: wordListToFreqDict(originallist)


1
这几乎不是实现此目的的“最佳”方法。您只需要对文本进行一次遍历即可计算单词的出现频率,而在这里您只需对每个唯一的单词进行遍历。
juanpa.arrivillaga

它甚至没有为每个唯一单词添加约束。
MonsieurBeilto
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.