如何利用Python计算列表中出现的单词数量

431 阅读5分钟

简介

在Python中计算一个列表元素中的词频是一项比较常见的任务--特别是在创建分布数据时,为 直方图.

假设我们有一个列表['b', 'b', 'a'] - 我们有两个出现在 "b "上,一个出现在 "a "上。本指南将向你展示三种不同的方法来计算Python列表中的单词出现的数量。

  • 使用 Pandas 和 Numpy
  • 使用count() 函数
  • 使用集合模块的Counter
  • 使用一个循环和一个计数器变量

在实践中,你会使用 Pandas/Numpy、count() 函数或Counter ,因为它们使用起来相当方便。

使用Pandas和Numpy

通过Numpy和Pandas,以一种易于操作的格式获得数值计数的最短和最简单的方法(DataFrame)。我们可以将列表包装成一个Numpy数组,然后调用pd 实例的value_counts() 方法(该方法对所有DataFrame 实例也可用)。

import numpy as np
import pandas as pd

words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']

pd.value_counts(np.array(words))

这将产生一个包含的DataFrame

hello      3
goodbye    1
bye        1
howdy      1
hi         1
dtype: int64

你可以访问它的values 字段来获得计数本身,或者index 来获得单词本身。

df = pd.value_counts(np.array(words))

print('Index:', df.index)
print('Values:', df.values)

这样的结果是:。

Index: Index(['hello', 'goodbye', 'bye', 'howdy', 'hi'], dtype='object')

Values: [3 1 1 1 1]

使用*count()*函数

获取列表中单词出现次数的 "标准 "方法(没有外部库)是通过使用列表对象的count() 函数。

count() 方法是一个内置函数,它以一个元素为唯一参数,并返回该元素在列表中出现的次数。

count() 函数的复杂度是O(n),其中n 是列表中存在的因子数量。

下面的代码使用count() 来获得一个单词在列表中出现的次数。

words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']

print(f'"hello" appears {words.count("hello")} time(s)')
print(f'"howdy" appears {words.count("howdy")} time(s)')

这应该会给我们带来与之前使用循环相同的输出。

"hello" appears 3 time(s)
"howdy" appears 1 time(s)

count() 方法为我们提供了一个简单的方法来获得列表中每个单词的出现次数。

使用集合模块的计数器

Counter 类实例可以用来,嗯,计算其他对象的实例。通过向其构造函数传递一个列表,我们实例化了一个Counter ,它返回一个列表中的所有元素及其出现次数的字典。

从那里,要得到一个词的出现,你可以用这个词作为字典的一个键。

from collections import Counter

words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']

word_counts = Counter(words)

print(f'"hello" appears {word_counts["hello"]} time(s)')
print(f'"howdy" appears {word_counts["howdy"]} time(s)')

这样就得到了。

"hello" appears 3 time(s)
"howdy" appears 1 time(s)

使用一个循环和一个计数器变量

最终,一个强硬的方法,即循环浏览列表中的每一个词,当找到这个词时,将一个计数器递增1,然后返回总的词数,也是可行的

当然,这种方法随着列表大小的增加,效率会越来越低,只是在概念上容易理解和实现。

下面的代码在count_occurrence() 方法中使用了这种方法。

def count_occurrence(words, word_to_count):
    count = 0
    for word in words:
        if word == word_to_count:
          # update counter variable
            count = count + 1
    return count


words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']
print(f'"hello" appears {count_occurrence(words, "hello")} time(s)')
print(f'"howdy" appears {count_occurrence(words, "howdy")} time(s)')

如果你运行这段代码,你应该看到这样的输出。

"hello" appears 3 time(s)
"howdy" appears 1 time(s)

很好,很简单!

最有效的解决方案?

当然--如果你要处理大量的词库,你会寻找最有效的解决方案。让我们对所有这些方案进行基准测试,看看它们的表现如何。

这个任务可以分解为寻找所有单词的出现次数或单个单词,我们将对这两种情况进行基准测试,从所有单词开始。

import numpy as np
import pandas as pd
import collections

def pdNumpy(words):
    def _pdNumpy():
        return pd.value_counts(np.array(words))
    return _pdNumpy

def countFunction(words):
    def _countFunction():
        counts = []
        for word in words:
            counts.append(words.count(word))
        return counts
    return _countFunction

def counterObject(words):
    def _counterObject():
        return collections.Counter(words)
    return _counterObject
    
import timeit

words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']

print("Time to execute:\n")
print("Pandas/Numpy: %ss" % timeit.Timer(pdNumpy(words)).timeit(1000))
print("count(): %ss" % timeit.Timer(countFunction(words)).timeit(1000))
print("Counter: %ss" % timeit.Timer(counterObject(words)).timeit(1000))

其结果是

Time to execute:

Pandas/Numpy: 0.33886080000047514s
count(): 0.0009540999999444466s
Counter: 0.0019409999995332328s

与其他变体相比,count() 方法非常快,但是,它不像其他两种方法那样给我们与计数相关的标签。

如果你需要标签--Counter ,它比将列表包裹在Numpy数组中然后计数的低效率过程要好。

另一方面,你可以利用DataFrame的方法进行排序或其他操作,这是你无法做到的。Counter 也有一些独特的方法。

最终,你可以使用Counter 来创建一个字典,并把字典也变成一个DataFrame ,以利用Counter 的速度和DataFrames 的多功能性。

df = pd.DataFrame.from_dict([Counter(words)]).T

如果你不需要标签--count() ,那就可以了。

另外,如果你要找一个单字

import numpy as np
import pandas as pd
import collections

def countFunction(words, word_to_search):
    def _countFunction():
        return words.count(word_to_search)
    return _countFunction

def counterObject(words, word_to_search):
    def _counterObject():
        return collections.Counter(words)[word_to_search]
    return _counterObject

def bruteForce(words, word_to_search):
    def _bruteForce():
        counts = []
        count = 0
        for word in words:
            if word == word_to_search:
              # update counter variable
                count = count + 1
            counts.append(count)
        return counts
    return _bruteForce
    
import timeit

words = ['hello', 'goodbye', 'howdy', 'hello', 'hello', 'hi', 'bye']

print("Time to execute:\n")
print("count(): %ss" % timeit.Timer(countFunction(words, 'hello')).timeit(1000))
print("Counter: %ss" % timeit.Timer(counterObject(words, 'hello')).timeit(1000))
print("Brute Force: %ss" % timeit.Timer(bruteForce(words, 'hello')).timeit(1000))

其结果是

Time to execute:

count(): 0.0001573999998072395s
Counter: 0.0019498999999996158s
Brute Force: 0.0005682000000888365s

蛮力搜索和count() 方法优于Counter ,主要是因为Counter 本身就计算所有的词而不是一个

总结

在本指南中,我们探索了在Python列表中寻找单词的出现,评估了每种解决方案的效率,并权衡了每种解决方案何时更适合。