如何在Python3中使用matplotlib绘制词频

来自菜鸟教程
跳转至:导航、​搜索

介绍

文本数据以多种不同的形式存在,从新闻到社交媒体再到电子邮件。 当我们分析和可视化文本数据时,我们可以揭示可以改变我们解释文本方式的总体趋势。

在本教程中,我们将探索在文本语料库中绘制词频。 我们将要创建的程序将搜索纯文本文档并按频率组织每个唯一单词。 然后,我们将使用 matplotlib 绘制我们找到的数据。

先决条件

为了能够使用本教程,请确保您具有以下先决条件:

最后,确保您遵循 Step 1 — importing matplotlib of our How to Plot Data in Python 3 Using matplotlib,因为必须为此项目安装 matplotlib .

第 1 步 — 设置程序文件

现在我们已经在我们的计算机上安装了 matplotlib,我们可以开始创建我们的项目了。

使用您选择的文本编辑器,创建一个新的 Python 文件并将其命名为 word_freq.py。 这将是我们的主要文件。

在这个程序中,我们将 import matplotlib 和我们需要的 class (即 pyplot),传递给它 [X128X ] 别名。 这实质上将 plt 声明为将在整个脚本中使用的全局变量。

word_freq.py

import matplotlib.pyplot as plt

接下来,我们将在 Python 中导入一些默认包。 这些将用于设置和接受命令行输入。 需要注意的重要包是argparse。 这就是我们将用来从命令行获取信息并包含用户帮助文本的内容。

让我们在 Python 中导入以下默认包:

word_freq.py

import matplotlib.pyplot as plt
import sys
import operator
import argparse

最后,创建标准的 main 方法并调用。 在 main 方法中,我们将编写大部分代码。

word_freq.py

import matplotlib.pyplot as plt
import sys
import operator
import argparse


def main():

if __name__ == "__main__":
  main()

现在我们已经导入了所有内容并为我们的项目设置了骨架,我们可以继续使用我们导入的包。

第 2 步 - 设置参数解析器

对于这一部分,我们将创建命令行参数并将它们存储在 变量 中以便快速访问。

在我们的 main 方法中,让我们创建解析器变量并将其分配给 argparse 提供的默认构造函数。 然后我们将为我们将在文件中查找的单词分配预期的参数。 最后,我们将为包含该单词的文件分配预期的参数。 这将是一个 .txt 文件。

word_freq.py

...
def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      "word",
      help="the word to be searched for in the text file."
  )
  parser.add_argument(
      "filename",
      help="the path to the text file to be searched through"
  )

if __name__ == "__main__":
  main()

现在,方法中的第一个参数是我们期望在命令行中的标题。 第二个参数 help= "..." 用于向用户提供有关命令行参数应该是什么的一些信息。

接下来,我们将给定的参数保存到另一个变量中,我们将调用 args

word_freq.py

...
def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      "word",
      help="the word to be searched for in the text file."
  )
  parser.add_argument(
      "filename",
      help="the path to the text file to be searched through"
  )

  args = parser.parse_args()

if __name__ == "__main__":
  main()

为了更好地衡量,我们应该始终检查我们的输入,以防命令行参数中出现拼写错误。 这也是为了防止我们的脚本突然崩溃。 因此,让我们通过使用 try 语句来处理错误。

word_freq.py

...
def main():
    ...
    args = parser.parser_args()

    try:
        open(args.filename)

    except FileNotFoundError:
        sys.stderr.write("Error: " + args.filename + " does not exist!")
        sys.exit(1)

if __name__ == "__main__":
  main()

我们正在使用 sys.exit(1) 向用户指示代码存在问题并且无法成功完成。

我们的项目现在将能够接受命令行参数。 下一步是解析我们的输入文件。

第 3 步 — 解析文件

在这一步中,我们将获取一个文件,读取每个单词,记录它们出现的频率,并将其全部保存到字典数据类型中。

让我们 创建一个名为 word_freq() 的函数 ,它接受两个命令行参数(单词和文件名),然后在 main() 中调用该函数。

word_freq.py

...
def main():
    ...
    word_freq(args.word, args.filename)

def word_freq(word, filename):

if __name__ == "__main__":
  main()

解析文件的第一步是创建一个字典数据类型,我们称之为 doc。 这将保存文件中找到的每个单词并跟踪它出现的次数。

word_freq.py

...
def word_freq( word, filename ):
    doc = {}

if __name__ == "__main__":
  main()

下一步是遍历给定的文件。 这是使用嵌套的 for 循环 完成的。

第一个 for 循环旨在打开文件并从中获取第一行。 然后它获取每一行中的内容,并根据单词之间的空白字符字符串将其拆分,同时将单词存储到数组中。

第二个 for 循环获取这个数组,并循环检查它是否在字典中。 如果是,我们将其添加一个计数。 如果不是,那么我们创建一个新条目并将其初始化为 1。

word_freq.py

...
def word_freq(word, filename):
    doc = {}

    for line in open(filename):
        split = line.split(' ')
        for entry in split:
            if (doc.__contains__(entry)):
                doc[entry] = int(doc.get(entry)) + 1
            else:
                doc[entry] = 1

if __name__ == "__main__":
  main()

现在我们已经完成了该项目的一半。

回顾一下,our main() 方法应该设置我们的命令行输入并将它们传递给 word_freq() 函数。 word_freq() 应该从命令行获取单词和文件名,并保存在文本文件中找到的每个唯一单词。

接下来,我们将获取这些数据并组织它以在我们的图表中使用。

第 4 步 — 存储和排序数据

在我们制作图表之前,我们必须确保这个词确实在我们打开的文件中。 我们可以使用 if 条件语句 来做到这一点。

word_freq.py

...
def word_freq(word, filename):
    ...
      else:
          doc[entry] = 1
    if (not word in doc):
        sys.stderr.write("Error: " + word + " does not appear in " + filename)
        sys.exit(1)

if __name__ == "__main__":
  main()

现在我们知道这个词在文件中,我们可以开始为我们的图表设置数据。

首先,我们必须从出现次数从高到低对字典数据类型进行排序,并初始化变量以供以后使用。 我们必须对字典进行排序,以便它在图表上适当地可视化。

word_freq.py

...
def word_freq(word, filename):
    ...
    if (not word in doc):
        sys.stderr.write("Error: " + word + " does not appear in " + filename)
        sys.exit(1)

    sorted_doc = (sorted(doc.items(), key = operator.itemgetter(1)))[::-1]
    just_the_occur = []
    just_the_rank = []
    word_rank = 0
    word_frequency = 0

if __name__ == "__main__":
  main()

需要注意的两个变量是 just_the_occur,它是保存单词出现次数的数据。 另一个变量是 just_the_rank,它将保存有关单词排名的数据。

现在我们有了排序字典,我们将遍历它以找到我们的单词及其排名,并用这些数据填充我们的图表。

word_freq.py

...
def word_freq( word, filename ):
    ...

  sortedDoc = (sorted(doc.items(), key = operator.itemgetter(1)))[::-1]
  just_the_occur = []
  just_the_rank = []
  word_rank = 0
  word_frequency = 0

    entry_num = 1
    for entry in sorted_doc:
        if (entry[0] == word):
            word_rank = entryNum
            word_frequency = entry[1]

        just_the_rank.append(entry_num)
        entry_num += 1
        just_the_occur.append(entry[1])

if __name__ == "__main__":
  main()

在这里,我们必须确保两个变量 just_the_occurjust_the_rank 的长度相同,否则 matplotlib 将不允许我们创建图形。

我们还在循环中添加了一个 if 语句来查找我们的单词(我们已经知道它在那里)并提取它的排名和频率。

现在我们拥有了创建图表所需的一切。 我们的下一步是最终创建它。

第 5 步 - 创建图表

此时我们可以插入我们一开始创建的plt变量。 要创建我们的图表,我们需要一个标题、y 轴标签、x 轴标签、比例和图表类型。

在我们的例子中,我们将创建一个以 10 为底的对数图来组织我们的数据。 标题和轴标签可以是您希望它们成为的任何内容,但描述性越强,对查看您的图表的人来说就越好。

word_freq.py

...
def word_freq( word, filename ):
    ...
  just_the_rank.append(entry_num)
  entry_num += 1
  just_the_occur.append(entry[1])

  plt.title("Word Frequencies in " + filename)
  plt.ylabel("Total Number of Occurrences")
  plt.xlabel("Rank of word(\"" + word + "\" is rank " + str(word_rank) + ")")
  plt.loglog(
    just_the_rank,
    just_the_occur,
    basex=10
  )
  plt.scatter(
    [word_rank],
    [word_frequency],
    color="orange",
    marker="*",
    s=100,
    label=word
  )
  plt.show()

if __name__ == "__main__":
  main()

标题、plt.ylabel()plt.xlabel() 函数是每个轴的标签。

plt.loglog() 函数分别将 just_the_rankjust_the_occur 作为 x 和 y 轴。

我们更改日志基数并将其设置为 10。

然后,我们将绘图设置为分散并突出显示我们的观点。 我们把它做成了一颗橙色的星星,大小为 100,所以它很明显。 最后,我们用我们的话给它贴上了标签。

一旦我们的图表的一切都完成了,我们告诉它用 plt.show() 显示。

现在我们的代码终于完成了,我们可以测试运行它了。

第 6 步 — 运行程序

对于我们的文本示例,我们需要一个文本文件来读取,所以让我们从 Project Gutenberg 下载一个,这是一个为读者提供免费电子书(主要是公共领域)的志愿者项目。

让我们将查尔斯狄更斯的小说 A Tale of Two Cities 的文本保存为一个名为 cities.txtcurl 的文件到我们当前包含 Python 脚本的目录中:

curl http://www.gutenberg.org/files/98/98-0.txt --output cities.txt

接下来,让我们运行我们的代码,传递我们选择的单词的参数(我们将使用“fish”)和文本文件的名称:

python word_freq.py fish cities.txt

如果一切正常,您应该会看到:

我们看到“鱼”这个词的排名是 5309,并且是出现次数的可视化。

现在,您可以继续尝试不同的单词和不同的文本文件。 您可以通过阅读我们的 How To Handle Plain Text Files in Python 3 教程来了解有关处理文本文件的更多信息。

完成的代码和代码改进

此时,您应该有一个功能齐全的程序,它将确定 .txt 文件中给定单词的词频。

下面是我们为这个项目完成的代码。

word_freq.py

import matplotlib.pyplot as plt
import sys
import operator
import argparse


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "word",
        help="the word to be searched for in the text file."
    )
    parser.add_argument(
        "filename",
        help="the path to the text file to be searched through"
    )

    args = parser.parse_args()

    try:
        open(args.filename)
    except FileNotFoundError:

        # Custom error print
        sys.stderr.write("Error: " + args.filename + " does not exist!")
        sys.exit(1)

    word_freq(args.word, args.filename)


def word_freq(word, filename):
    doc = {}

    for line in open(filename):

        # Assume each word is separated by a space
        split = line.split(' ')
        for entry in split:
            if (doc.__contains__(entry)):
                doc[entry] = int(doc.get(entry)) + 1
            else:
                doc[entry] = 1

    if (word not in doc):
        sys.stderr.write("Error: " + word + " does not appear in " + filename)
        sys.exit(1)

    sorted_doc = (sorted(doc.items(), key=operator.itemgetter(1)))[::-1]
    just_the_occur = []
    just_the_rank = []
    word_rank = 0
    word_frequency = 0

    entry_num = 1
    for entry in sorted_doc:

        if (entry[0] == word):
            word_rank = entry_num
            word_frequency = entry[1]

        just_the_rank.append(entry_num)
        entry_num += 1
        just_the_occur.append(entry[1])

    plt.title("Word Frequencies in " + filename)
    plt.ylabel("Total Number of Occurrences")
    plt.xlabel("Rank of word(\"" + word + "\" is rank " + str(word_rank) + ")")
    plt.loglog(just_the_rank, just_the_occur, basex=10)
    plt.scatter(
        [word_rank],
        [word_frequency],
        color="orange",
        marker="*",
        s=100,
        label=word
    )
    plt.show()

if __name__ == "__main__":
    main()

现在一切都已完成,我们可以对这段代码进行一些潜在的改进和修改。

如果我们想比较两个单词的频率,那么我们将在命令行参数中添加一个额外的单词位置。 为此,我们必须为单词添加另一个检查器并为单词添加更多变量。

我们还可以修改程序,以便比较每个单词与另一个单词的长度。 为此,我们将按长度比较单词并将每个唯一长度保存到字典中。

结论

我们刚刚创建了一个程序来读取文本文件并组织数据,以查看特定单词与文本中其他单词的频率相比。

如果您对数据可视化感兴趣,还可以查看我们的 如何使用 JavaScript 制作条形图和 D3 库 教程。