社交媒体挖掘(二)

7 数据可视化


到目前为止,已经学习了如何从社交媒体收集、加工和处理数据。数据分析的下一步是运用可视化来更好地理解发现。

可视化是即刻理解数据的最有有效方法。例如,图表可以帮助我们了解数据随时间的变化,用颜色编码的电子表格可以清楚地显示数据集中各个数据值的范围。

在这一章中将要讨论如何对前一章分析的 Twitter 机器人数据使用可视化,在 Google
Sheets 中使用图表和条件格式工具来更深入地了解这些数据。

通过图表了解机器人账户

在第 6 章中,使用了数字取证研究实验室开发的一个标准来确定 Twitter 的@sunneversets100 账户是否是一个自动的"机器人"账户。再次回顾一下实验室的标准:每天发 72 次以上推特的可能是机器人,而每天发 144 次以上推特的可以确认是机器人。在前一章中获取的数据中发现有很多天@sunneversets100 账户发送的推文比这两个标准都要多的多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 在第 6 章的结尾,还把机器人的行为与正常人的进行比较(图 7-1)。

图 7-1:比较可疑的机器人账户和人控账户每日推文频率的表格

该表格清楚地显示:@sunneversets100 账户每日推文的数量远远超过用于比较的人控账户。但是,仅通过阅读推文或查看该表格中的值不能直观的感受这一情况。这就是图表等数据可视化工具可以提供帮助的地方。

选择图表

图表以及数据驱动的图形可以让人即刻理解更多所展示数据代表的故事。可以使用形状(例如,圆形、矩形或直线)和颜色来比较值,也包括这些值是如何随时间变化的。可视化可以帮助受众一眼看到模式或关键发现。

但是在使用可视化之前,应了解图表具有不同的类型。一些图表主要是在统计学家或数据处理人员的圈子里使用,而另一些是普通大众熟悉的。重要的是:任何给定的图表都可能非常有效地传递一种类型的数据,但完全不能传递另一种类型的数据。由于这个原因,需要考虑使用图表来展示什么内容?好像前面讲的,数据分析有点像面试。确定每个问题的答案需要一组稍微不同的工具,对数据集提出问题可以帮助我们确定使用哪种图表来查找答案。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 选择正确的图表有时候很困难,但学者和图形编辑已经开发了许多指南。其中一个是:“Chart
Suggestions—A
Thought-Starter”,里面是一些最常见的数据可视化图形的对比(图 7-2)。

图 7-2:Andrew Abela 开发的指南

接下来讨论不同的图表类型及其用法。第一个是对不同的数据集进行比较,如:在上一章的分析中,比较了两个数据集:机器人和人类。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 常见用于比较数据的图是柱状图(图 7-3),该图绘制了在图 7-1 中的数据。

图 7-3:用于比较机器人和人类活动的柱状图

除了使用图表来比较各个数据点,还可以用图表来展示数据集的分布情况或值的范围。例如,把整个数据集划分为多个区(例如年龄段或等级 A 到 A–、B+到 B–等),然后计算每个区中有多少数量或占总体的百分比。

例如,在@sunneversets100 数据中可以查看每个推文被转发的分布情况。在图 6-3 所示的原始数据表格中,能够看到推文被转发数值的范围从 0 到 1-100、101-200、201-300。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 把图 7-2 中的流程图作为参考,发现对于像类似小分布的数据可以使用简单柱状图(图 7-4)。

图 7-4:每个推文转发数量的分布

有时想要了解整个数据集的构成,而不考虑年龄范围或转发数量等细分。可能只想看看数据集的构成,那么可以使用图表来理解数据集的部分与整体之间的关系。在图 7-4 中,可以看到大多数推文都有 1 至 100 次的转发,表明这些机器人吸引推文方面可能有些有效效果,但不是非常明显。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 机器人经常被用来放大别人的信息,也就说明机器人不会发布太多原创内容。介于这个原因查看@sunneversets100 账户的推文被转发的比例就会感到很有趣。图 7-5 的饼图展示了@sunneversets100 账户的推文中有 99.4%被转发。

图 7-5:饼图和环状图非常适合显示整体中类别的比例

最后但并非最终,使用图表展示数据类别可以呈现不同的关系。例如,询问一个值如何与另一个值关联,并研究一个列值的行为特征是否会导致另一个列值的减少或增加,或者一个列值是否与另一个列值的行为相关,这些关系都可以通过图表说明。

尝试理解一条推文被发送的时间和它被转发的次数之间的关系。在一天中一篇推文在转发参与度方面表现得是否特别好?确定这种关系最合适的图形是散点图,散点图是每个数据点沿着 x 轴和 y 轴放置的图形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 通常,研究人员感兴趣的是测量一个因变量或数据集如何受到一个无法控制的自变量或数据集的影响(比如降雨),这些因变量或数据集可能会由于外部因素而改变(雨伞的销售情况)。在某项研究中,研究人员想要找出降雨对雨伞销量的影响时,就可以使用散点图来观察两者之间的关系。散点图的惯例:自变量放在 x 轴上,因变量放在 y 轴上。同样的,给 Tweet 的推文数据提出如下问题:一天各个时间断对一条推文被转发的次数的有何影响?图 7-6 展示了一个图表,该图表给出了此问题的数据呈现。

图 7-6:一天的时间内@sunneversets100 被转发推文的散点图

时间序列的具体说明

在开始制作图表之前需要认识的最后一个方面就是使用数据集的时间序列。对数据集提出的问题通常要求指定一个特定的时间点或更长的时间段。要绘制时间序列的图表,必须把数据按照时间聚合为小块,例如:推文的时间戳,或者更小的时间单位(如一个月或一年)。

在前一章中,使用数据透视表记录了@sunneversets100 和@nostarch 的每日推文,从而为图表创建了一个时间序列。然后,根据两个数据集共有的时间范围使之合并。这就可以把两个账户放在一起并排对比了。

至此已经学习了选择正确数据可视化的方法,现在看看如何在 Google
Sheets 中制作这些图表。

制作图表

制作一个图表的一般步骤如下:

1. 提出一个问题。

2. 进行数据分析来回答这个问题。

3. 选择最好的图表格式和工具来回答的问题。

4. 以所选图表工具能够理解的方式格式化和安排数据。

5. 插入或选择数据,然后使用工具创建图表。

与 Microsoft Excel 一样,Google
Sheets 提供了一套有用的绘图工具,可以直接在电子表格中添加快速图形。为了使这个练习简单,使用上一章中的数据制作一个图表。现在按照列出的步骤进行图表的制作过程。

通过分析试图回答的核心问题是:机器人的行为如何与人类的行为相比较?为回答这个问题所做的分析得出了一个大致三星期的时间序列。这就完成了步骤 1 和步骤 2。

接下来是选择最佳的图表进行分析。正在尝试比较的是两个数据集------机器人和人类的日常推文活动------并且想要按照时间显示这种比较。图 7-2 中的流程图建议使用柱状图。

然后就是格式化数据。正如在上一章中讨论的,处理数据(无论是 Google
Sheets 还是 python)的一个核心部分弄清楚是每个电子表格列包含的数据类型并将其格式化。此步骤有助于工具和编程语言正确解释数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 在柱状图中沿着 x 轴绘制时间值,并沿着 y 轴绘制数值(每个帐户每天发出的推文数量)。因此,应该确保 Google
Sheets 在一列中接收日期的值,在另外两列中接收数字的值(图 7-7)。

图 7-7:包含了绘制随时间变化所需所有值的表格

运用在第 6 章所学到的知识,选择含有日期的列数据,然后选择Format ▸ Number

Date
来格式化这些数据成为日期型数据。选择含有账户活动记录的列,然后选择Format
▸ Number ▸ Number
把它们格式化为数值型数据。

下一步中需要选择使用哪种图表来绘制数据的图形。与之前一样,确保选择了所有要在图形中呈现的数据。选中含有日期和记录的数据列-然后选择Insert
Chart

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 完成上述操作后 Google
Sheets 会把一个图表直接插入到表格中(图 7-8),同时会打开一个称为图表编辑器(Chart
Editor
)的窗口。

图 7-8:显示机器人和人类大约三周的 Twitter 活动的图表

该图表编辑器可以让我们修改图表,其由两个选项卡组成:数据 Data 和自定义 Customize。在 Data 选项卡中,可以调整或修改图表的内容,如:选择用来制作图表的单元格的范围、设置某一行中的值为图表标题。在本练习中,在Chart
type
下拉菜单中选择Column chart(柱状图)。

在图表编辑器的自定义选项卡中,可以风格化我图表,例如:更改图表的标题、设置坐标轴的最小值或最大值、为图表文本选择不同的字体。现在使用选择菜单项Series更改表示机器人数据的颜色。通过鼠标的点击会展开一个下拉菜单,其中包含绘制的两个数据系列------机器人数据和人类数据。每个数据系列通常以列标题命名。在本练习中选择@sunneversets100 并使用桶(bucket)图标下的调色板(color
palette)更改该列的颜色。

最后但并非最终,通过单击图表右上角的三个点并选择"Move to own
sheet…
"选项把刚刚生成的图表移动到属于它自己的工作表上。在用图表呈现数据时数据集的细微差别在更大的屏幕上更容易看到。

虽然没有探索由 Google
Sheets 提供的所有类型的图表,但是本章列出的原则应该有助于理解在深入研究数据可视化之前需要采取的那些步骤。通过询问关于数据的问题,预先考虑想要探究的内容。如果遵循本章所述的过程,那么可以更容易地确定可视化数据的正确方法。

条件格式

到目前为止,讨论了如何将数据可视化为图表,以便读者更容易理解。虽然许多人在学校、工作或媒体中遇到图表和图形,但很少有人知道在电子表格中格式化数据的替代工具。这些工具允许您可视化地分析数据,而不需要经历创建图表的过程。

Google Sheets 中一个特别有用的功能是条件格式(conditional
formatting
),此工具根据条件为电子表格中的单元格上色。这个功能有点像在电子表格中编写 if 语句。例如,创建一个单元格中的值满足特定的条件则使用特定的颜色填充单元格的条件格式。可以把条件格式描述为一个机器人使用荧光笔遍历电子表格,根据设置的规则更改单元格的颜色。

单色格式

通过在 Twitter 数据集上应用条件格式来理解其的工作原理。假设想要以一种快速的方法来判断 Twitter 数据集中账户活动的某个值是否高于数字法医研究实验室给出的阈值,通过条件格式设置让 Google
Sheets 对值等于或大于 72(且小于 144)的数字的任何单元格显示一种颜色,对于值等于或大于 144 的数字的任何单元格显示另一种颜色。

在使用条件格式之前,先要选中应用规则的单元格。然后,选择Format ▸
Conditional Formatting
,这会在 Google
Sheets 中打开一个称为条件格式规则的窗口。

现在进行把单色格式应用于表格中数据的操作,单色格式是根据条件将一种颜色应用于一组单元格上。把所有包含从 72 到 143 的数字的单元格涂成黄色的步骤是:在"Single
Color
"选项卡的窗口中,选择"Format cells if…“选项,在"Add
another rule
"下选择"Is
between
”。这时窗口应该显示两个输入框,可以在其中指定最小值和最大值。若要把符合条件的单元格染成黄色,则单元格必须包含符合指定范围的值。对于 Twitter 数据集,输入的最小值为 72,最大值为 143。然后在"格式样式"下选择黄色即可。

若要添加另一个条件格式规则,请在"Single Color"选项卡中选择"Add
another rule
",“Format cells if…”,但这里选择"Is greater than
or equal
to
",并把值设置为 144。然后,在"格式样式"下,选择不同的颜色(如:红色)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 设置了这两个规则后,Google
Sheets 应会把含有 72 到 143 的值的单元格涂成黄色,把等于或大于 144 的涂成红色(图 7-9)。

图 7-9:根据条件格式规则着色的表格

在 Google
Sheets 中不仅可以使用单色格式来为单元格设置单独的格式,而且还可以设置多种颜色的单元格格式。

色阶格式

Google
Sheets 可以使用色阶,而不仅仅单色来格式化单元格。如果使用色阶,Google
Sheets 会检查所选中的所有单元格,找到其中的最小值和最大值,然后依据色阶为每个单元格进行着色。如果还没有想好采用哪种图表来呈现数据,那么可以采用色阶查看数据集分布。

打开色阶格式(color scale
formatting)后操作步骤和单色格式相同:选中数据,选择"Format ▸
Conditional Formatting
",然后在条件格式规则窗口选择"**Color
scale"**标签(图 7-10)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 虽然色阶格式不像单色格式那样精确,但它是一种非常有用的可视化工具。色阶格式用于比较数据集的值。单色格式可以设置特定的阈值。之前例子中的问题是哪些日期揭示了@sunneversets100 账户是一个机器人账户,该问题需要一个正确或错误的答案:在任何一天,机器人是否发出 144 次或更多的推文?相比之下,色阶格式更多带有一种探索性目的:不太清楚阈值是多少,也不知道如何限定一个值,但是想了解手上数据的范围和分布。

图 7-10:应用色阶格式的表格

概要

经过本章的学习,了解了 Google
Sheets 提供的各种可视化工具。虽然没有查看每种图表类型工作原理,但现在应该对 Google
Sheets 可视化的工作方式有了大致的了解。

Google
Sheets 易于导航的按钮和菜单是应用可视化来熟悉数据分析的好方法。当在下一章开始进行更多代码驱动的数据分析时,读者会发现可以应用从本章学到的概念------为正确的分析类型转换正确的数据进行可视化。

8 数据分析的高级工具


在前一章中,了解了通过使用诸如 Google
Sheets 之类的简单工具,可以分析数千行来自机器人活动的数据。虽然 Microsoft
Excel 和 Google
Sheets 可以处理大量数据(Excel 有超过 100 万行和 16,000 列,谷歌有 400,000 个单元格),但这些工具可能不适合对数百万或数十亿行复杂的数据进行分析。

在网络上用户每天创建数十亿的帖子、推文、回复和其他类型的在线数据。处理如此体量的信息对于想要在更大范围内调查人类网络行为的数据侦探来非常重要。为此需要熟悉能够处理大型数据文件的编程分析工具。即使您不经常使用这些工具,在决定使用哪种工具时,了解这些工具的功能也是非常有用的。

本章中将会练习使用 Python 读取和研究数据。在此过程中,您将了解更多与编程相关的工具和概念,读者将学习如何设置虚拟环境,这是一种使用库的本地化方式。在此之后,将会展示如何使用应用程序 Jupyter
Notebook,该界面可用于编写和修改代码、输出结果以及呈现文本和图表。最后会安装一个能够进行统计分析的 Python 库------Pandas。如同在前几章中的学习过程一样,读者将通过一个实际的练习来吸收所有这些新知识------提取和探索 Reddit 数据。

使用 Jupyter Notebook

在前面的章节中通过命令行接口(CLI)和脚本使用了 Python。对于读者来说,这是一种快速且直接地熟悉编程语言的好方法。

但是,当使用 Python 技能并编辑更复杂的脚本时,应该尝试使那些更容易管理分析项目、结构化和可共享的工具。因为脚本越复杂,跟踪分析的每个步骤就越困难。

本节是学习如何使用 Jupyter
Notebook 的地方。Jupyter 是一个开源 Web 应用程序,可在计算机上本地运行,并在 Chrome 之类的浏览器中呈现。Jupyter
Notebook 可以一次运行多行代码,或以块的形式运行脚本,这样在迭代和改进代码时更容易调整部分代码。Jupyter
Notebook 程序是从 Web 应用程序 IPython
Notebooks 演变而来的,其创建目的:容纳三种编程语言(Julia,Python 和 R(Ju-Pyt-R)),但此后演变为能够支持许多其他编程语言。

Jupyter
Notebook 也被许多不同领域的数据科学家使用,包括:处理各种数字来提高网站性能的人、社会学家研究人口信息等等。使用 Jupyter
Notebook 的好处是:数据科学家和研究人员可以把他们的 Jupyter Notebook
(通常以详细和注释性的分析为特色)放在像 GitHub 这样的代码共享平台上,让像您这样的初学者更容易地复制他们的研究。

设置虚拟环境

想要使用 Jupyter
Notebook,需要学习三个重要的概念,这些概念会让您的编码技能提升到一个新的水平。

首先要能够创建和理解虚拟环境。虚拟环境(Virtual
Environment)这个词可能很难让人理解,所以从虚拟环境的用途开始。

正如前几章中学习到的,每次要使用库时必须通过在命令行接口(CLI)中输入命令来导入。每个库都安装在计算机上,在卸载之前会一直停留在那里。

对于刚刚开始使用库的 Python 开发人员,他们的工作可能只需要一个或两个库就能完成。但随着您成为一个更成熟的研究人员时,就需要越来越多的库来处理不同的任务。例如:一些任务可能需要一个能够识别 PDF 图像文件中文本的库,而另一些任务可能需要一个能够对一个网站进行截屏的库。当提高技能并处理更多不同的项目时,可能需要在计算机上安装越来越多的库,库之间可能存在冲突。虚拟环境就是解决这种冲突的工具。

虚拟环境通过把库安装在指定的环境中来解决冲突的问题。可以把它想象成为每个项目创建的平行宇宙,可以在不影响计算机整体环境的情况下进行实验。虚拟环境就像计算机内部的另一台计算机,能够利用编程库的强大功能,而不必担心这些库与计算机的其他部分发生冲突。

尽管可以使用各种第三方工具来创建虚拟环境,但在本项目中使用 Python
3 的内置虚拟环境工具。不过,首先需要创建一个 python_scripts 项目文件夹来存储的 Jupyter
Notebook。之后打开命令行接口并切换至该文件夹。例如:把 python_scripts 文件夹存在 Mac 系统的 Documents 文件夹中时可以在命令行接口中输入命令,然后回车:

在 Windows 系统则输入如下命令,注意其中的区别:

切换至该文件夹后就可以通过运行一个命令来创建虚拟环境,如果是 Mac 系统:

在 Windows 系统则输入:

对创建虚拟环境的命令进行分解:首先告知命令行接口在 Mac 上使用 python3(PC 上使用 python)命令。接着是参数-m,告诉 python3 调用内置于 Python 中的模块。本命令中使用了虚拟环境模块 venv。最后给虚拟环境起了一个名字 myvenv。

运行该命令后应会在 python_scripts 文件夹中创建一个名称为 myvenv 的文件夹。在 myvenv 文件夹中会安装所有将要使用到的库。

至此虚拟环境设置完成了。但是想要进入该虚拟环境需要将其激活。可以通过在命令行接口中输入相关命令来激活和关闭虚拟环境。

如果命令行接口仍在 python_scripts 文件夹中,只需输入:

同样对该命令进行分解后分别理解。source 是 Mac 系统一个内置的命令,目的是运行指定的路径中包含的源代码(source 命令也可以用句点替换,所以代码".
myvenv/bin/activate"同样有效)。在此命令中,路径是 myvenv/bin/activate,该路径告诉计算机切换至当前目录中 myvenv 文件夹,然后切换至 myvenv 中的 bin 文件夹,最后运行 bin 中的 activate 文件。activate 文件包含一个用来激活虚拟环境的脚本。

命令运行完成后虚拟环境就被激活了!通过查看命令行接口来判断是否已激活:命令行接口的提示符应该以字符串(myvenv)开头。要停用或关闭虚拟环境,只需输入命令 deactivate,命令行接口的提示符的字符串(myvenv)就会消失。

组织 Notebook

尽管不需要遵循特定的文件夹结构,但尽早组织输入数据、Notebook 文件和输出数据,可以防止以后进行分析时出错。因为尽早养成良好的习惯比以后破坏习惯容易。

现在创建三个单独的文件夹,这些文件夹存储在 python_scripts 文件夹中,但不在 myvenv 文件夹中。首先创建一个名为 data 的文件夹来存储输入数据,其中包含已从 API 或网站接收,下载或抓取的数据文件。然后创建一个 output 文件夹,其中将包含分析过程中导出的任何电子表格。在本书中的例子中不会创建电子表格,但是对于数据分析师来说,拥有一个 output 文件夹是一种很好的常规做法。在"使用系列和数据框架"中介绍 pandas 库时使用一个名为.to_csv()的简单函数,该函数到处有关分析的 csv 文件。最后把 Jupyter
Notebook 创建的文件保存在一个名为 notebooks 的文件夹中。

可以在计算机上手动创建这些文件夹或目录,但也可以使用 mkdir 命令以编码的方式创建。在命令行接口中切换至 python_scripts 文件夹(如果仍位于 myvenv 文件夹中,请使用"cd
…"向上移动)并输入以下三行:

命令 mkdir 采用指定的名称创建目录。完成这三个命令会创建刚才描述的三个文件夹。或者,可以使用 mkdir 后跟所有三个用空格分隔文件夹名称,如下所示:

安装 Jupyter 并创建第一个 Notebook

Jupyter 可以创建 Notebook 文档,此类文档可以读取不同种类的代码,如:Python 和 Markdown(用于格式化文档的语言)等。由于 Notebook 能够读取各种编程语言,因此 Notebook 可以将 Python 代码的结果与 Markdown 文本一起呈现,从而使程序员更易于注释其分析。

像其他 Python 库一样通过 pip 从网上下载 Jupyter
Notebook 并安装本地的计算机上。安装 Jupyter Notebook 的命令如下:

安装过程结束后,通过在命令行接口中输入以下命令打开 Jupyter Notebook:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 输入此命令后,Jupyter
Notebook 将启动本地服务器(该服务器仅在本地计算机上运行),并在默认的 Web 浏览器中打开一个窗口(作者的默认浏览器为 Chrome,如[图 8-1所示]{.ul}。读者打开的应该时自己经常使用的浏览器)。

图 8-1:Jupyter 界面

在这个界面里可以切换至工作文件夹并在其中创建文件。切换至 notebooks 文件夹中,从下拉菜单中选择"New

Python3
"。完成后就会在 notebooks 文件夹中创建一个新的 notebook 文件,并在一个新的浏览器选项卡中打开该 notebook 文件。

Jupyter
Notebook 咋看起来很像普通的文本文档软件,具有编辑工具和完整的选项菜单。当然,这些都是根据 Python 开发人员的需要定制的。Jupyter
Notebook 有一个特别棒的功能,使用单元(cells)一次运行不同的 Python 代码块。换句话说可以把 Python 代码分隔成多个单元并逐个运行。

使用单元

默认情况下 notebook 文件打开后会创建一个单元,可在其中输入文本和代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 用鼠标选中包含此代码的单元,然后按"Run"按钮(或使用快捷键 SHIFT-ENTER)来执行刚在单元中键入的 Python 代码。然后计算机应在单元格正下方打印出代码结果,同时创建第二个单元,如图 8-2 所示。

图 8-2:在 Jupyter 中两个单元

这里需要注意:Jupyter 运行了单元后,单元左侧的方括号将不再为空。由于刚刚在 Notebook 中运行的是第一个单元,因此左侧的方括号中应显示数字 1。当使用不同的代码运行相同的单元时会发生什么情况呢?修改第一个单元格内的代码:

现在单击单元左侧的区域来选中该单元格(蓝色条应突出显示当前所选单元格的左侧),然后再次单击"Run"按钮。单元下应显示字符串"Hello!",与之前的字符串"Hi"一样。但是现在单元左侧的方括号应该包含数字 2。因此,Jupyter
Notebook 不仅跟踪运行单元,还记录运行的单元顺序。

由于 Jupyter
Notebook 中的代码分为多个单元,因此这种跟踪方式在后续的分析过程中会让查找错误变得非常方便。与从上到下运行脚本文件不同,单元可以不按照代码顺序运行该代码。跟踪可以准确告诉您 Notebook 已经运行了哪些代码,以及仍需要运行哪些代码。这可以帮助避免在使用 Jupyter 时发生的常见错误,如:当一个单元中的代码引用尚未运行的单元中定义的变量。

与 Microsoft Word 或 TextEdit 等文本编辑软件类似,Jupyter
Notebook 在可视界面中提供了许多出色的工具。可以使用工具栏执行以下操作:例如保存(软盘图标),剪切单元(剪刀图标),添加单元(加号)以及向上(向上箭头)或向下(向下箭头)移动单元。

至此了解了如何在 Jupyter
Notebook 中运行 Python 代码单元的基础知识。但是,随着通过重写、重新运行、删除或移动单元来改进 Notebook 代码来进行更多的试验时,可能会发现在 Notebook 的内存中存储了很多"垃圾"。例如,创建一些变量后最终决定删除它,或者存储以后不再使用的数据。这些垃圾会使 Notebook 运行速度变慢。那么,如何在不破坏在单元中编写的代码的情况下,清除在 Notebook 运行中产生的所有 Python 代码的内存?

有一个不错的技巧:转到菜单并按照顺序点击"Kernel
Restart"后,就能清除所有先前运行代码时产生的"垃圾"以及单元左边方括号内的所有数字。如果再次运行一个单元,就应该呈现该段代码的结果,并在方括号重新显示数字 1。

还有一个可以按顺序运行多个单元的技巧。为了说明技巧,先把另一个单元添加到笔记本中(选中第一个单元后,点击加号(+)按钮)。然后在第二个单元中输入以下代码:

再添加另外两个单元,并在里面分别输入如下代码:

若要依次运行所有四个单元格,选中第一个单元格(其中包含代码:print(“Hello!”)),然后在菜单中依次点击"Cell
▸ Run All
Below
"。此操作会自动运行被开的 Notebook 文件中选中的单元与之下的所有单。如果其中某个单元格包含错误,Jupyter
Notebook 会在错误的单元处停止运行并显示出错误代码。

Jupyter Notebook 可用于多种任务,以上讨论的基本步骤应能让您把 Jupyter
Notebook 作为数据分析工具。Jupyter
Notebook 可以运行在脚本文件中编写的所有代码。通过把代码分成多个单元,然后一次运行一个代码块,就可以直接运行本书之前编写的脚本了。

现在完成了解如何使用 Jupyter
Notebook 后,接下来就是如何使用 pandas 查看 Reddit 数据。

PANDAS 是什么?

在之前的章节中学习了如何使用各种 Python 库来收集数据。现在需要了解一个可以帮助分析数据的库。

尽管可能已经猜到:Pandas 库与可爱的熊猫毫无关系。这个库的名字实际上来源于面板数据的概念------由创建者 Wes
McKinney 建立的用来处理大型跨时间跨度测量的数据集。Pandas 允许 Python 从各种数据源(包括 csv、tsv、json 甚至 Excel 文件)获取数据,并能轻松地合并数据集。

与 Jupyter 和其他 Python 库一样,使用之前先要安装 Pandas(pip install
pandas)。若已按照之前的所有说明操作并打开了 Jupyter
Notebook,就说明已经在命令行接口中运行了本地服务器。要在不中断本地服务器的情况下安装 Pandas,可以在终端中打开一个新窗口或命令提示符,然后切换至相同的项目文件夹,再次激活虚拟环境,最后安装 Pandas 库。

完成安装之后就需要导入 Pandas 库。在 Jupyter
Notebook 中最传统的方法是在单元中输入一个 import 命令并运行:

该命令运行之后就完成了导入 pandas 库的步骤,然后就能够在之后的代码中使用缩写pd访问 pandas 库的函数。例如,可以写 pd.Series([12,53,57])而不是 pandas.Series([12,53,57])。这个导入命令是许多使用 pandas 的数据分析人员的一种默认约定,这有助于保持代码整洁和易于阅读。现在开始创建、读取和操作一些数据结构!

使用序列(Series)和数据框(DataFrame)

可以加载到 pandas 中的最简单的数据结构是一个序列(series),序列有点类似于列表(List)或数组(Array)。通过 series()函数在 panda 中生成一个序列。

在 Jupyter Notebook 新单元中输入如下代码来生成一个序列:

代码➊把列表(12,53,57)存储在变量 numbers 中。在代码➋中调用导入 Pandas 时的缩写pd,紧随其后的是 Series()函数以及在函数内输入的参数 numbers。该段代码的功能是:使用 Series()函数来创建类型为 Series 的数据对象,并将列表 numbers 放入这个 Series 中。这与在第 4 章中访问另一个库 Beautiful
Soup 中函数的方法相同:首先通过分配给一个缩写来引用这个库,然后通过缩写访问其提供的函数。完成输入后运行该单元的结果如下:

这就是 pandas 表示一个简单数据序列的方式,也可以称其为一维数据集。在输出的左侧显示了一个列,该列表示每个数据的索引(或称其为:位置)。按照 Python 的惯例,索引从 0 开始每一行递增 1。输出的右侧是实际的数据值。在序列的最后还会看到用冒号分隔的单词:dtype(数据类型)和 int64(整型)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 序列可能是最简单的一种数据集,因它只有一列数据,而且每一行只包含一个值。但在 pandas 中使用更多的是多列多行的二位数据集:数据框(DataFrame)。可以把数据框视为是比起 Excel 和 Google
Sheets 容纳更多数据且由 Python 读取的电子表格。与电子表格不同,数据框有索引index(行标签)和列columns
(列标签)组成。

通过 pandas 的内置 DataFrame()函数就能创建数据框。在一个新单元中,输入以下代码行:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 使用变量 numbers2➊来存储数据,然后该变量 numbers 被赋予一个字典(dictionary),该字典"one"被赋予一个 list([1.2,
2, 3,
4]),"two"被赋予另一个 list([4,3,2.5,-1])。此处为了便于阅读,两个字典项中添加了换行符,但其不会影响代码的运行。运行此单元后的输出图 8-3 所示。

图 8-3:数据框显示为一个表

与序列相同,该数据框具有一个索引(index),以列的形式出现在最左边。数据框中还有两个列(columns)数据,分别命名为"one"和"two",其中包含字典中的数据。

读取和探索大型数据文件

数据集的大小和详细程度各不相同------有些数据集非常容易理解,而另一些数据集则非常复杂、庞大而且难以处理。社交媒体数据尤其难于处理:在线用户生成大量数据和内容,而这些数据和内容反过来又会产生许多反响、评论和其他响应。

当处理来自社交媒体公司、学者或其他数据存档人员的原始数据时,这种复杂性可能会变得更加严重。通常,研究人员收集的数据比他们进行单独分析所需要的数据要多,因为对一个大数据集提出各种问题要比为可能在目标和范围上发生变化的项目反复收集较小的数据集要容易得多。

由于 API 的限制,研究人员、记者和其他分析人员很难跟踪媒体操纵活动、恶意攻击或其他短期在线现象。在网上这种例子很多,在本书中就不再一一累述了。

作为对策,各种机构和个人已经开始收集和存储这些社交媒体数据。例如,互联网档案馆(Internet
Archive)每月进行一次数据提取,并在其服务器上托管数百万条推文。研究人员就能将这些推文用于语言或其他分析。学者们收集并存档了 Facebook 上的信息,试图理解一些社会现象。

虽然这些努力对实证研究非常有帮助,但产生的数据可能对如我们这样的数据侦探构成挑战。通常,在对数据进行有意义的分析之前,必须花费大量的时间来研究、探索和"了解"这些数据。

在接下来的几页中,将要学习如何阅读和浏览一个大型数据文件。在本章及以后的章节中,还将介绍数据档案管理员 Jason
Baumgartner 提供的 Reddit 数据集,他认为将社交媒体数据提供给学者和其他类型的研究人员至关重要。该数据集包含 2014 年至 2017 年之间 r/askscience 提交在 Reddit 论坛或 subreddit 上的所有数据,人们可以对该数据集提出与科学有关的问题。在本章的其余部分,还将通过 Pandas 来了解数据集的结构和大小。该数据集的下载地址:https://pan.baidu.com/s/1IjnXCkAdKgpbXczjh2UpMA。

当完成下载 Reddit 数据集后,将其解压至 python_scripts 文件夹的 data 文件夹中,然后返回至 Jupyter
Notebook 的界面中。按照惯例,Notebook 中的第一个单元包含 import pandas as
pd 命令,因为所有 import 语句应首先运行。在第二个单元中通过输入如下所示的代码加载 data 文件夹中的 csv 文件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 指定名称为 ask_science_data 的变量用于存储 Reddit 数据集。然后,使用等号(=)为该变量分配一个 Pandas 函数 read_csv()创建的数据框。read_csv()函数需要将数据文件的路径作为参数(通常是 csv 文件,但 read_csv()也可以处理 tsv 和 txt 文件,只要这些文件包含用逗号、制表符或其他一致的分隔符分隔的数据即可)。如果采用非逗号分隔符,则必须在 read_csv()函数中指定第二个参数,该参数应是代表这些分隔符的字符串。由于在 Jupyter
Notebook 中运行该命令,因此第一个参数中的路径反映的是数据文件相对于 Notebook 文件的相对位置。使用两个点和正斜杠可以让命令切换到当前文件夹上一层的文件夹,在本例中为项目文件夹(python_scripts)。然后命令会自动按照输入的路径参数切换至包含名称为 askscience_subsmissions.csv 文件的 data 文件夹中。

考察数据集

不同于 Microsoft Excel 或 Google
Sheets 之类的程序(这些程序是为用户通过可视界面操作数据而构造的),Pandas 实际上不会一次显示整个数据框。在上述的代码运行完成后 Pandas 并没有显示任何数据。这是因为把 read_csv()的输出分配给了一个变量,而不是输出或打印该变量。如果在未分配变量的情况下运行该函数,或者在其中运行了含有 ask_science_data 变量的单元,则会看到一小段数据。虽然这种截断会让人刚赶到困惑,但这种设置也节省了许多计算机的计算能力。当打开包含几十万行数据的文件时,某些软件可能会崩溃或运行变慢,这种情况取决于软件的复杂程度。因此,通过不显示完整的数据框 Pandas 可以更有效地处理大数据集。

这种特性表明需要找到一种方法来读取数据集的不同部分。Pandas 的开发者已经考虑到这种情况,只需要通过 Pandas 中一些便捷的功能就能轻松完成此任务。

若要查看数据集的前几行,可以使用一个 head()的函数。此函数接收整数作为唯一参数,如果不输入任何内容,则参数的默认值为 5。因此,如果想查看数据集的前 10 行,则可以在 Notebook 的单元中运行一下命令:

执行这个命令时,首先调用 ask_science_data 变量,该变量保存通过 csv 文件读取的数据。然后对变量包含的数据调用 head()函数,在 Jupyter
Notebook 中的输出应如图 8-4 所示的数据框。如果想要查看数据集最后 10 行,可以使用 ask_science_data.tail(10)代码,其输出与图 8-4 中类似。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-4:显示数据框中的前 10 行

虽然不能一次看到全部数据,但这不是很重要。现在的需求是:考察数据集。这代表想知道的是,每个列中值的类型以及列名是什么?通过查看数据的前 10 行或后 10 行会有所帮助。

但可能已经注意到由于数据集的列比较多,必须往侧边滚动才能显示数据集的每一列。这种操作可能有点麻烦。Pandas 中的一些内置工具可以显示数据集的部分概要。

可以对数据集进行转置(transpose),把列转为行,把数据转为列。转置可以翻转整个数据框------这种操作看起来有点像逆时针旋转了 90 度的表。通过调用 Pandas 中的 T 属性实现转置的功能:

若要查看数据框的所有列名(可以作为一个 list 输出),可以使用一下代码:

想要获得数据框重所有数据类型的摘要,可以使用 dtypes 属性:

最后,可以使用 Python 内置的函数显示数据框的行数。是否记的在第一章中使用的 print()函数在交互式 shell 中显示信息?在第一章使用 print()结合 len()来显示的字符串或列表的长度。在这里也可以使用这些函数来查看数据框包含的数据有多少:

这段代码看起来有点复杂。首先,使用 len()函数通过传递参数 ask_science_data(数据集)来测量数据框的长度(即:数据框包含的行数)。换句话说,首先通过函数获取的是 ask_science_data 数据框的长度。当单独使用 len()时仅在 Jupyter
Notebook 单元中没有其他语句跟随的情况下才显示结果,所以最好将它放在 print()函数中,这样就可以确保单元显示 len()所测量的结果。

如果使用的是与本书相同的数据集,那么 Jupyter
Notebook 的输出应该是 618576。这个数字就是数据框包含的数据量。

如果通过传递 ask_science_data.columns 作为 len()的参数,可以得到数据框的列数:

ask_science_data 数据框应包含 65 个不同的列。因此,把 65 列乘以 618,576 行就能够得出 ask_science_data 数据框还有的数据值超过 4,000 万个。

这里译者还要介绍一个更加方便查看查看数据框大小的属性 shape(),这个属性能够直接以元组(一个不能修改其中值的列表)的形势输出数据框的大小:

查看特定的行和列

知道如何获取数据框的结构意味着明白如何鸟瞰手中的数据。但如果想更仔细地查看数据的特定部分,该怎么办呢?

在方括号中加入包含在数据框的变量后,可以选择或索引该数据框不同的数据子集。例如,要查看特定的列时可以在方括号内指定该列名称的字符串:

上述代码可以显示 Reddit 数据集中 title 列。也可以使把显示的数据储存在变量中:

还可以同时查看多个列,通过把需要查看的列名称储存在一个 list 中,然后将这个 list 传递给数据框:

Pandas 还提供了其他方法来实现比上述更加复杂的查询功能。正如在本章前面提到的,数据框中的每一行都有一个索引,索引的作用有点像一个标签。默认情况下,Pandas 为每一行分配一个整数作为索引(也可以为每一行分配自定义索引,但在本练习中不进行这样的操作)。Pandas 提供了 iloc[]方法调用任何给定行,方法是将行索引号放在方括号内(在编程术语中,这称为基于整数位置的索引):

如果在 Jupyter
Notebook 的单元中运行该代码,就会在输出的位置显示 Reddit 数据集的第 5 行(编程通常从 0 开始计数,Pandas 也沿袭了这种业内的默认设定)。

还可以把上面提到的两种方法结合起来。例如,如要调出名为 title 列第 5 行中的值:

由于要处理的数据是包含数百万个值的大型电子表格,通过以上一些方法可以更好地了解该数据集。到这里相信读者已经掌握了所有的基础知识,接下来就可以开始学习如何使用数据进行计算了。

概要

本章带领读者了解了如何探索大型数据集,此过程是任何数据分析重要的第一步。只有在理解了数据的本质------内容、格式和结构之后,才能找到最佳策略来分析数据中包含的意义。

在下一章中将继续研究 Jupyter Notebook,并使用 Jupyter
Notebook 探索对数据集提出问题的方法。

9 在 REDDIT 数据中寻找趋势

社交媒体数据中的部分数据以定量的方式列举人类行为,而另一部分则是定性的方式。例如,可以通过计算 Reddit 帖子"点赞"来衡量它的受欢迎程度,这就可以对其进行简单的聚合,如:在特定时间段内帖子获得点赞数的平均或中位数。然而,Reddit 上相类似数据的其他部分可能很难用定量的方式进行处理,如:帖子的评论在内容和风格上可能大相径庭。

比起计算像"点赞"这样的参与度指标(如:平均值),想要总结(或者说量化)人们讨论的话题及其讨论方式是非常困难的。但不可避免的,对社交网络上的数据进行有意义的分析需要同时观察这两种信息。然而,学习如何做到这一点对于我们非常有用,因为可以探索真实人的行为、思想和反应(也可能是机器人!)。

在本章中,将会学习如何浏览定性和定量信息。我们将通过分析第 8 章中的 r/askscience 数据,探讨人们如何与社交媒体中的疫苗接种主题互动,并从数据集中提出针对性的问题。首先,将通过搜索 subreddit 中带有词干 vaccin(例如:vaccinatevaccination)一词的提交内容,来尝试更好地理解如何处理基于文本的信息。然后会比较疫苗贴与非疫苗贴的参与度,即:评论和点赞的总数。

明确研究目标

在这一章中使用来自 r/askscience 的 subreddit 在线帖子来衡量疫苗接种在网络上讨论的热度。

虽然 Reddit 用户并不能代表所有人,但仍可以通过对比论坛上的其他帖子来了解这个帖子在论坛上的热度。此过程的技术关键是:就像其他任何对社交网络的研究一样,需要承认和理解被研究的每个数据集的特殊性。

首先,提出一个最基本的问题:r/askscience 在 Reddit 上提交的含有"vaccine"、"vaccinate"等 vaccination 词变体的帖子,是否比不含这些词的帖子更活跃?

方法略述

回答问题的分析过程包含如下步骤:

1.
筛选数据并将其分组到两个数据框中。第一个数据框架包含所有使用单词 vaccine、vaccinate 或 vaccination 的帖子。第二个数据框包含没有提到这些词的帖子。

2.
在每个数据框上运行简单的计算。通过寻找平均或中位数的参与度指标来获得汇总数据(在本分析中,参与度指标由评论和点赞的组合数量表示),可以让我们更好地理解 r/askscience 数据的每个子集,同时为提出的问题给出答案。

在开始分析之前需要理解一些统计学术语。均值mean是将数据的所有值相加,并将和除以数据总个数的结果。中位数median是数据中所有值从小到大排序后,位于最大值和最小值之间的数。如果数据个数是偶数则取中间两个数的均值。均值和中位数都是集中趋势的度量(measures
of central
tendency)
,这些度量让我们可以通过查看某个中心点来评估数据集。当一个数据集含有非常多的数据且相对于数据集的总个数异常值outlier占比较小时,均值是度量其集中趋势的一个很好的方法。如果数据集中离群值的数量占比较大时可以通过中位数度量其集中趋势。

缩小数据范围

Reddit 数据集本身相当大,即使只看其中的一个子集 subreddit 其规模也超乎想象。虽然尽可能从包含全部数据的数据集开始对于分析非常重要,但是根据特定项目筛选数据可以更好地、更整洁地对其进行概述。筛选还能减少运行每个计算所需的时间。

本章还介绍了总体population和样本sample数据的概念,总体数据描述了包含指定组整体的数据集。此处的指定组包含了 r/askscience 在 Reddit 上 2014 年到 2017 年之间的所有帖子。样本数据是数据集的子集或样本。在本练习中会生成两个子集:一个包含与疫苗相关的帖子,另一个包含所有其他帖子。通过对这两个子集进行分析来比较它们之间的不同点。

本练习使用第 8 章中设置的虚拟环境和 Jupyter
Notebook。该练习在原有的 Notebook 文件上进行扩展,并且使用与之前练习的相同变量名称。

从特定列中选择数据

为了获取练习所需的数据,先 Reddit 数据集缩减到只包含与分析相关的列。然后删除那些包含不相关样本的行,如:空值 null。

在本练习中,我们对两种不同的数据特别感兴趣------帖子的标题和评论,包括:提交给 r/askscience 的文本,以及获得的反馈。如上一章所述,通过运行以下代码行可以把数据集的所有列名以列表的形式输出:

输出的结果是一个字符串列表,每个字符串代表一个列名:

以上显示了数据集有 62 个列。对于练习来说,只需要保留 title 列,ups 列以及 num_comments 列。

使用在上一张中提到的方法(“查看特定的行和列”),使用方括号在数据集中选中特定的列。现在确保已经打开了第 8 章的 Notebook 文件,并且已经运行了文件中的每个单元(Kernel
Restart & Run
ALL
)。然后,使用加号(+)在最底部的单元下面添加一个单元,并将清单 9-1 中代码输入其中:

清单 9-1:从数据集中选择感兴趣的列

首先创建一个名为 columns 的变量,并为其分配一个字符串列表,该字符串列表[“title”,
“ups”,
“num_comments”]包含想要储存在筛选后数据集的列。应确保每个列名的字符串与原数据集中的列名完全匹配,如果不匹配,无论是标点符号、大小写等拼写错误都可以导致 Python 脚本运行错误。

清单 9-1 的第二行代码创建了一个名为 ask_science_reduce 的变量,用于储存一个筛选后的数据框。此处应可以看到,改代码没有如之前那样在方括号中添加单个字符串,而是将包含列名的列表变量放在其中。将整个列表放在方括号中可以同时选择多个列。

至此,已经把数据集缩减到感兴趣的特定列,接下来筛选后数据集中删除包含与分析不相关值的数据行。

处理空值

在一个很大且不一致的数据集中,某些行或单元格可能不包含任何信息。这些"空(Null)"单元格可能完全不包含任何值,也可能仅包含占位符(placeholder),即:设计数据结构的机构或人员指派的任意字符串。如果可能的话,占位符会在数据字典(data
dictionary
)中被描述。数据字典是解释数据集内容、结构和格式的文档。一般情况下,必须自己通过研究数据集来了解。在最坏的情况是通过通过列名来猜测。还有一种简单的方法,就是通过询问收集数据的人来获取相关的信息。

在对数据进行解析的过程中,把这些空单元格称为空值。当在 Python 中试图在交互式 shell 或其他 Python 接口中打印空值时会返回 None。在 pandas 中空值被称为 NaN 值(not
a number 的缩写),数据框把 NaN 作为缺失数据单元格的占位符。

空值在收集到的社交媒体用户信息中特别常见。例如,收集到发布到 Facebook 视频链接的列数据仅包含用户实际发布视频的帖子的值。对于任何不包含视频的帖子,数据集都将没有该项的值,而且可能使用占位符(例如字符串"
no video"),也可能把该项留空,这意味着该项数据会是一个具有空值。

占位符,Null 和 NaN 值会导致分析发生错误。在应用函数或计算时,脚本会按照代码设定的步骤进行操作,当发现空值时都会发生错误并停止运行。本节中将介绍两种处理空值的方法,每种方法的目的不尽相同:一种是完全从数据中删除这些 null 值,另一种是保留整个数据集并将空值计数为零。

######## 删除空值

如果数据集中的某列包含空值,则删除包含空值的整行数据。在 Pandas 中使用 dropna()函数进行相关的操作。清单 9-2 显示了依据列是否包含 NaN 值删除整行数据的代码。

清单 9-2:删除列中包含 NaN 值的行

在没有特别规定的情况下,dropna()函数告诉 Pandas 从数据框中删除整行。但是 dropna()函数还有一些其他的参数,如:subset 参数。在此示例中,使用 subset 参数告诉 Pandas 在 ups 和 num_comments 列中删除包含 NaN 值的行。如果不给 dropna()函数传递任何参数,则 Pandas 默认删除具有任何 null 值的行。

######## 填充空值

为了标识 NaN 值但想要保留数据框的每一行数据,可以使用 fillna()函数。该函数用字符串或数字填充每个空值。清单 9-3 显示了如何使用 fillna()函数采用数字 0 填充 num_comments 列中的空值:

清单 9-3:用 0 填充空值

在清单 9-3 的代码中把 0 赋给 value 参数。此代把 num_comments 列中的空值替换为数字 0。

确定用删除空值的方式还是填充空值的方式,取决于数据集以及想要如何回答研究问题。例如,如果想要获取整个数据集评论数的中位数时是否可以确定地认为缺失值仅表示提交内容中没有相关的评论。如果能够确定,则可以用 0 填充这些值并进行相应的计算。

依据包含缺失值或"空单元格"的行数,评论数的中位数可能会发生显著变化。但由于此数据集有时把注释或注释的数量记录为零,有时也记录为空值,因此假定包含这些列的空值的行应视为 0(如果空值表示 0,可以假设数据集将不包含任何实际的 0,这是因为把 0 视为了一种符号而不是数字)。相反,认为这些缺失值是档案管理员无法捕获的数据,其原因:也许帖子在他收集这些信息之前就被删除了;也许这些指标是在某些年份中引入的而其他年份则没有。因此为了便于练习,应处理现有的数据并删除包含缺失值的 ups 或 num_comments 列的数据行,如清单 9-2 所示。

分类数据

下一步是根据关于疫苗接种的具体研究问题筛选数据。在进行筛选之前,需要对 Reddit 数据中关于疫苗接种的内容进行分类。

此处的分类方式是简化的。在处理大型数据集时简化分类是必经步骤,因为阅读每一篇文章并逐个对其解释是不可能实现的劳动密集型工作。即使可以雇佣一大群人阅读每个帖子并解释(在一些 prose-driven 项目中这种情况并不少见),但很难确保每个人都使用相同的标准来解释,这样做可能会使数据难以用标准的、可识别的方式分类。

在本章的示例中,把样本限制为包含单词 vaccination 及其变体的帖子,寻找 title 列中包含"vaccine"(在语言学中通常被称为词干,词干是一个词语去掉表示语法意义的词尾剩余的部分)的数据。该数据子集可能不能捕捉到关于疫苗接种的每一个帖子,但可以让我们定性地理解手头的问题。

通过在数据集中创建一个新列来依据帖子的标题 title 中是否包含字符串"vaccin"对数据集进行分类。新建列使用布尔值(也就是二进制值,True=1 或 False=0)填充。清单 9-4 显示了创建这个列所需的代码:

清单 9-4:根据某列是否包含某个字符串对新建列进行填充

在清单 9-4 中代码的等号左侧,使用方括号创建了一个名为 contains_vaccin 的新列。在等号右侧,使用了一个链式函数:首先使用方括号表示法从数据中选择 title 列,然后在该列上使用 str()函数将值转换为字符串,转换成字符串后就可以使用 contains()来确定列值是否包含"vaccin"。

这个链式函数的结果是一个布尔值:如果帖子的标题包含 vaccin,就返回 True;否则返回 False。代码运行后就会在 ask_science_dropped_rows 数据框生成一个新列 contains_vaccin,其值只有 True(1)或 False(0)。(译者注:清单 9-4 的代码再运行的时候会发生一个警告,但是不影响运行的结果。)

现在有了用于分类数据的列,就可以用这个列来筛选数据了。在 Jupyter
Notebook 的新单元中运行清单 9-5 中的代码:

清单 9-5:根据条件筛选数据

清单 9-5 中代码是否感觉很熟悉?在这里需要注意:在等号右侧的括号中使用了条件 ask_science_data_dropped_rows
[" contains_vaccin
"]==True。这段代码告诉 Pandas 检查 contains_vaccin 列中的值是否等于 True,这样就筛选到了一个数据集的子集,其中只包括词干中包含 vaccin 的数据。也可以设置条件等于 False,生成词干中不包含 vaccin 的子集:

至此已经生成了按照需求筛选的数据,现在可以查询一些有趣的见解。

汇总数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 为了确定 r/askscience 在 Reddit 上提交的包含"vaccine(接种)"、“vaccine(疫苗)”、"vaccinate(疫苗)"等不同单词的帖子是否比不包含这些词的帖子获得了更大的反响,可以查看这些帖子收到的被点赞和评论数的总和。

对数据进行排序

首先创建另一个新列,该列中的值是每行点赞和评论数量的和。该步骤在 Pandas 中是非常简单的操作(清单 9-6)。

清单 9-6:将多个列值合并在一列中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 在清单 9-6 中,在之前两个数据框中分别创建一个称为 combined_reactions 的列,并为其分配等于 num_comments 和 ups 列之和的值。运行此代码时可能会遇到 SettingWithCopyWarning 警告,SettingWithCopyWarning 是一个警告 Warning,而不是错误 Error。错误和警告之间的区别:错误使您的代码无法运行,而警告只是促使您仔细检查正在运行的代码是否在执行所需的操作。对于这本书,这里显示的代码可以完成想要做的事情:在注释数上添加点赞数。如果对发出此警告的开发人员希望进行何种调查感到好奇,请参阅http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html(该链接中的大致意思:Pandas 中的某些操作会返回数据的视图 View,某些操作会返回数据的副本 Copy。当对视图进行操作时就会发生 SettingWithCopyWarning,由于链式赋值 Chained
Assignment 以及隐蔽链式操作 Hidden
Chaining 也是对于视图的操作,所以也会发生 SettingWithCopyWarning。想要避免警告出现,建议如清单 9-1 以及 9-2 中在最后加上".copy()"。)

在新列中获得了 num_comments 和 ups 列之和的值之后,使用 sort_values()函数对该值进行排序,如清单 9-7 所示。

清单 9-7:使用 sort_values()对数据框进行排序

顾名思义,sort_values()函数是依据值的顺序对数据框进行排序。在清单 9-7 中给 sort_values()函数传递给了两个参数:by------告诉 Pandas 需要被排序的列;ascending------告诉 Pandas 排序的顺序(正向 True:从小到大/反向 False:从大到小)。在此处的代码中把 False 传递给 ascending 参数,数据会按照从大到小的顺序进行排序。

图 9-1 显示了对 ask_science_data_vaccinations 列进行排序后的数据框样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 图 9-1:Jupyter
Notebook 屏幕上 ask_science_data_vaccinations 的部分数据框按合并的参与总数排序

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 图 9-2 显示了 ask_science_data_no_vaccinations 列的一些结果。

图 9-2:Jupyter
Notebook 屏幕上 ask_science_data_no_vaccinations 的部分数据框按合并的参与总数排序

如图所示,ask_science_data_no_vaccinations 数据框中 combined_reactions 比与 ask_science_data_vaccinations 数据框中 combined_reactions 的值更大。对于这两个数据集中的前十大参与数据也是如此。ask_science_data_no_vaccinations 的前十帖子的合并参与总数要远远高于 ask_science_data_vaccinations。因此,以 r/askscience 数据的每个子集的前 10 帖子的参与总数衡量可以得出结论,与疫苗接种相关的帖子没有像其他主题那样获得了足够的关注。

但这里有个很大的问题:只看了前十名的帖子。对数据集进行筛选和排序可以帮助更好地理解数据集,但是只展示了大量数据集的极值。在下一节中,将进一步研究分析数据的一些不同方法。

对数据进行描述

一种常见的数据汇总方法是使用 mean()函数(清单 9-8)。

清单 9-8:mean()函数

在此使用 mean()函数来查找选中列(combined_reac)的平均值。当在一个单元中运行此代码后,应能得到以下数字:

对 ask_science_data_no_vaccates 数据框运行相同的代码及其输出,如下所示:

这些数字表明,不包含 vaccin 帖子的平均合并参与总数高于包含 vaccin 的帖子。换句话说,之前的结论—包含 vaccin 的帖子合并参与总数更少,因此这些帖子没有从 Reddit 其他用户那里获得更多的注意力,与对合并参与总数排名前 10 的帖子进行观察得出的结论相同。

平均值只是汇总的一种方法。可以使用 describe()函数在 Pandas 中一次查看多个指标(清单 9-9)。

清单 9-9:describe()函数

该函数的输出结果如下:

此摘要包括行数 count、均值 mean、标准差 std、最小值 min、25%分位数、50%分位数(中位数)和、最大值 max。

让在另一个单元中运行与 ask_science_data_no_vaccates 相同的代码:

该代码的输出结果如下:

以上输出展示了两个数据框的中位数是相同的,中位数是衡量一个帖子参与度的另一种方法。然而,这里的平均值可能是比较帖子数据的最佳方式,因为两个数据集的中位数都是 1,不能在一个数据集与另一个数据集之间的使用中位数做出明确的区分。

最后但并非最终,当展示对于数据的发现时,给刚刚运行的各种分析提供上下文环境非常重要。虽然向受众展示中位数和均值可能会有所帮助,但对数据所做的一切保持透明也至关重要。数据分析需要理解上下文环境:不仅要展示信息数据的范围,还须概括如何对数据进行分和任何其他有用的观察。

其中一个观察结果可能是观察数据子集的分布。如前所述,均值和中位数均旨在帮助度量数据集的集中趋势,但是在这种情况下它们的差异很大:两个数据子集中点赞和评论总数的中位数均为 1,而与疫苗接种相关与不相关子集的平均值为 13 和 16。通常,这种差异应促使进一步检查数据集的分布(在第 7 章中简要介绍了数据集分布的概念),其中可能包含了一些不寻常的特征。例如,考虑到数据的两个子集的中位数都是 1,可以认定至少有一半的帖子获得了 1 或更少的点赞和评论,这一事实是值得关注的。

无论最终在演示文稿,论文或文章中写什么,重要的是要描述数据本身、使用的过程、找到的结果以及任何可能有助于受众充分了解分析的上下文环境。

概要

在本章中学习了如何使用处理、筛选和分析数据等各种步骤来思考研究问题。介绍了根据列中的潜在值对社交媒体数据进行分类和筛选的步骤。然后学习了如何对这些筛选后的数据集进行简单的数学计算。

重要的是:了解到有不止一种方法来处理这样的分析。这点可以从技术上体现出来:某些数据分析人员可能选择使用不同的功能来执行在本章中所做的各种筛选和汇总。在其他情况下,研究人员可能会尝试使用不同的方法论方法并思考不同的方法来对数据进行分类和汇总。例如,另一位开发人员可能使用了另一种方法来对有关疫苗接种的帖子进行分类,他们可能已根据多个词对数据进行了筛选。尽管一些固执己见的在线用户可能会这么想,但用数据来回答问题并没有万无一失的方法,但用我们拥有的数据做更多的实验并尝试用不同的方法来回答相同的研究问题还是很有帮助的。

在本章中,我们使用分类驱动的细分来汇总数据集,而在下一章中将研究如何汇总不同时间段的数据。

数据集介绍:多类道路车辆目标检测数据集 一、基础信息 数据集名称:多类道路车辆目标检测数据集 图片数量: - 训练集:7,325张图片 - 验证集:355张图片 - 测试集:184张图片 总计:7,864张道路场景图片 分类类别: - Bus(公交车):城市道路与高速场景中的大型公共交通工具 - Cars(小型汽车):涵盖轿车、SUV等常见乘用车型 - Motorbike(摩托车):两轮机动车辆,含不同骑行姿态样本 - Truck(卡车):包含中型货运车辆与重型运输卡车 标注格式: YOLO格式标注,包含归一化坐标的边界框与类别标签,适配主流目标检测框架。 数据特性: 覆盖多种光照条件与道路场景,包含车辆密集分布与复杂背景样本。 、适用场景 自动驾驶感知系统开发: 用于训练车辆识别模块,提升自动驾驶系统对道路参与者的实时检测与分类能力。 交通流量监控分析: 支持构建智能交通管理系统,实现道路车辆类型统计与密度分析。 智慧城市应用: 集成至城市级交通管理平台,优化信号灯控制与道路资源分配。 学术研究领域: 为计算机视觉算法研究提供标准化评测基准,支持多目标检测模型优化。 三、数据集优势 高场景覆盖率: 包含城市道路、高速公路等多种驾驶环境,覆盖车辆静止、行驶、遮挡等现实场景。 精细化标注体系: 采用YOLO标准格式标注,每张图片均经过双重质检,确保边界框与类别标签的精准对应。 类别平衡设计: 四类车辆样本量经科学配比,避免模型训练时的类别偏向问题。 工程适配性强: 可直接应用于YOLO系列模型训练,支持快速迁移至车载计算平台部署。 现实应用价值: 专注自动驾驶核心检测需求,为车辆感知模块开发提供高质量数据支撑。
内容概要:本文介绍了DeepSeek与Mermaid结合实现可视化图表自动化生成的技术及其应用场景。DeepSeek是一款由杭州深度求索人工智能基础技术研究有限公司开发的大语言模型,具有强大的自然语言处理能力,能理解复杂的自然语言指令并生成对应的Mermaid代码。Mermaid是一款基于文本的开源图表绘制工具,能够将简洁的文本描述转化为精美的流程图、序列图、甘特图等。两者结合,通过DeepSeek将自然语言转化为Mermaid代码,再由Mermaid将代码渲染成直观的图表,极大提高了图表制作的效率和准确性。文章详细描述了DeepSeek的发展历程、技术架构及应用场景,Mermaid的基础语法和图表类型,并通过一个电商平台开发项目的实战演练展示了者结合的具体应用过程。 适合人群:具备一定编程基础和技术理解能力的研发人员、项目经理、数据分析师等。 使用场景及目标:①需求分析阶段,快速生成业务流程图和功能关系图;②设计阶段,生成系统架构图和数据库设计图;③实现阶段,辅助代码编写,提高编码效率;④验证阶段,生成测试用例和测试报告图表,直观展示测试结果。 阅读建议:在学习和使用DeepSeek与Mermaid的过程中,建议读者结合具体项目需求,多实践生成图表和代码,熟悉两者的交互方式和使用技巧,充分利用官方文档和社区资源解决遇到的问题,逐步提高图表绘制和代码编写的准确性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值