介绍
文本数据以多种不同的形式存在,从新闻到社交媒体再到电子邮件。 当我们分析和可视化文本数据时,我们可以揭示可以改变我们解释文本方式的总体趋势。
在本教程中,我们将探索在文本语料库中绘制词频。 我们将要创建的程序将搜索纯文本文档并按频率组织每个唯一单词。 然后,我们将使用 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_occur
和 just_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_rank
和 just_the_occur
作为 x 和 y 轴。
我们更改日志基数并将其设置为 10。
然后,我们将绘图设置为分散并突出显示我们的观点。 我们把它做成了一颗橙色的星星,大小为 100,所以它很明显。 最后,我们用我们的话给它贴上了标签。
一旦我们的图表的一切都完成了,我们告诉它用 plt.show()
显示。
现在我们的代码终于完成了,我们可以测试运行它了。
第 6 步 — 运行程序
对于我们的文本示例,我们需要一个文本文件来读取,所以让我们从 Project Gutenberg 下载一个,这是一个为读者提供免费电子书(主要是公共领域)的志愿者项目。
让我们将查尔斯狄更斯的小说 A Tale of Two Cities 的文本保存为一个名为 cities.txt
和 curl
的文件到我们当前包含 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 库 教程。