Pandas

数据科学的严肃从业者使用完整的科学方法,从问题和假设开始,然后探索数据以确定假设是否成立。但在许多情况下,例如当您不太确定数据包含什么时,执行一些探索性数据分析会很有帮助——只是四处看看,试图看看是否可以找到一些东西。

而且,这就是我将在这里介绍的内容,使用由令人惊叹的 Python 生态系统为数据科学提供的工具,有时被称为 SciPy stack。在过去一两年里,我遇到过很多人,他们专门为了数据科学的需求而学习 Python,这怎么强调都不过分。当我在两年前为我的博士论文分析数据时,我被告知 Python 尚未成熟到足以完成我需要的那种事情,我应该改用 R 语言。我确实想知道现在情况是否已经转变;SciPy stack 的贡献者和贡献数量惊人,使其成为更具吸引力的数据分析平台。

在我的文章“分析数据”中,我描述了如何过滤日志文件,将它们变成包含感兴趣信息的 CSV 文件。在这里,我解释了如何将该数据导入 Pandas,Pandas 提供了额外的灵活性,并让您以各种方式(包括图形化方式)探索数据。虽然我不一定会得出任何惊人的结论,但您至少会看到如何将数据导入 Pandas,以各种方式对其进行切片和切块,然后生成一些基本绘图。

Pandas

NumPy 是一个 Python 包,可以从 Python Package Index

(PyPI) 下载,它提供了一种称为 NumPy 数组的数据结构。这些数组虽然可以从 Python 访问,但主要在 C 中实现,以实现最大速度和效率。它们也以向量为基础运行,因此如果您将 1 添加到 NumPy 数组,您实际上是在将 1 添加到该数组中的每个元素。适应这种思维方式以及数组应具有统一数据类型的事实需要一段时间。

现在,您可以对 NumPy 数组做什么?您可以对其应用任意数量的函数。幸运的是,SciPy 定义并提供了大量的函数,适用于您可能想要执行的几乎每种科学和数学研究。

但在这种情况下,以及在数据科学领域的许多情况下,我真正想做的是从各种格式读取数据,然后探索这些数据。实现这一目标的完美工具是 Pandas,这是一个专为 Python 中的数据分析而设计的广泛库。

Pandas 中最基本的数据结构是“series”(序列),它基本上是 NumPy 数组的包装器。一个序列可以包含任意数量的元素,为了获得最大效率(和合理性),所有元素都应为相同类型。序列的关键在于您可以设置任何您想要的索引,从而为您提供比 NumPy 数组中可能实现的更强的表达能力。Pandas 还为序列对象提供了一些额外的功能,形式为大量方法。

但 Pandas 的真正强大之处在于“data frame”(数据帧),它有点像在 Python 内部实现的 Excel 电子表格。一旦您在数据帧中获得信息表,您就可以执行各种操作和计算,通常以类似于关系数据库的方式工作。实际上,您可以在数据帧上调用的许多方法在名称上与您可以在 SQL 中调用的操作相似或相同。

如果您已经安装了可用的 Python,那么安装 Pandas 并不是很困难。最简单的方法是使用 pip,即标准的 Python 安装程序来执行此操作


sudo pip install -U numpy matplotlib pandas

上述命令将安装许多不同的软件包,如果安装了较旧版本的软件包,则会覆盖现有安装。

尽管 Pandas 已经很出色了,但当它与 SciPy stack 的其余部分以及 Jupyter(即 IPython)notebook 集成时,它会变得更加出色。您也可以安装它


sudo pip install -U 'jupyter[notebook]'

不要忘记引号,这确保了 shell 不会尝试将方括号解释为 shell globbing 的一种形式。现在,一旦您安装了它,请运行 Jupyter notebook


jupyter notebook

如果一切顺利,shell 窗口应该会填充一些日志文件输出。但此后不久,您的 Web 浏览器将打开,让您有机会(使用页面右侧的菜单)打开一个新的 Python 页面。其想法是,您随后将与此文档进行交互,在各个单元格内输入 Python 代码,而不是将它们放在文件中。要执行单元格内的代码,只需按 Shift-Enter 键;单元格将执行,并且将显示评估最后一行的结果。

即使我不是在数据科学领域工作,我也会发现 Jupyter Notebook 是一种极其简洁、易于使用且方便的方式来处理我的 Python 代码。它已经取代了我对基于文本的 Python 交互式 shell 的使用。退一步说,我可以跨会话保存并返回到单元格这一事实意味着我花更少的时间重新创建上次处理项目时的工作状态。

在 Jupyter Notebook 内部,您需要加载 NumPy、Pandas 和各种相关功能。最简单的方法是结合使用 Python import 语句和 notebook 中的 %pylab magic function


%pylab inline
import pandas as pd
from pandas import Series, DataFrame

上述操作确保了您需要的一切都已定义。从理论上讲,您不需要将 Pandas 别名为 pd,但 Pandas 世界中的每个人都这样做。我必须承认,我在一段时间内避免使用此别名,但最终决定,如果我希望我的代码与其他人的项目完美集成,我真的应该遵循他们的约定。

读取 CSV

现在让我们读取我为我的上一篇文章创建的 CSV 文件。您可能还记得,该文件包含许多列,这些列由制表符分隔,这些列是从 Apache 日志文件中创建的。事实证明,CSV 虽然是一种看似原始的信息交换格式,但它是数据科学领域最流行的方法之一。因此,Pandas 提供了各种函数,可让您将 CSV 文件转换为数据帧。

最简单和最常见的此类函数是 read_csv。正如您可能期望的那样,read_csv 可以接收文件名作为参数,它将读取该文件名并将其转换为数据帧。但是 read_csv,就像 Pandas 中的许多其他 read_* 函数一样,也可以接受文件对象甚至 URL。

我首先尝试使用 read_csv 方法读取 access.csv,即我上一篇文章中的 CSV 文件


df = pd.read_csv('access.csv')

不幸的是,这失败了,并出现了一个非常奇怪的错误消息,指示文件的不同行包含不同数量的字段。经过一番思考和调试,结果发现此错误是因为文件包含制表符分隔的值,并且 pd.read_csv 的默认设置是假定逗号分隔符。因此,您可以重试加载,传递 sep 参数


df = pd.read_csv('access.csv', sep='\t')

果然,它奏效了!此外,如果您请求刚刚创建的 Pandas 数据帧的键,您将获得文件顶部定义的标头。您可以通过要求数据帧向您显示其键来查看这些标头


df.keys()

现在,您可以将数据帧视为 Excel 电子表格的 Python 版本或二维关系数据库中的表,但您也可以将其视为一组 Pandas 序列对象,每个序列对象提供一个特定的列。

我应该注意到,read_csv(以及 Pandas 中的其他 read_* 函数)是真正令人惊叹的软件。如果您尝试从 CSV 文件中读取数据,但 Pandas 没有正确处理它,那么您要么有一个非常奇怪的文件格式,要么您还没有找到正确的选项。

在数据帧中导航

现在您已将 CSV 文件加载到数据帧中,您可以对其执行哪些操作?首先,您可以要求查看整个数据帧,但就此示例 CSV 文件而言,它有超过 27,000 行,这意味着将其打印出来并浏览它可能不是一个好主意。(也就是说,当您在 Jupyter 中查看数据帧时,您只会看到前几行和后几行,这使其更易于处理。)

如果您将数据帧视为电子表格,则可以查看单个行、列以及它们的组合。

您可以使用方括号中的列(键)名称甚至作为属性来请求整个列。因此,您可以通过请求 “r” 列来获取所有请求的 URL,如下所示


df['r']

或像这样


df.r

当然,这仍然会导致打印大量行。您可以使用 Python 切片语法仅请求前五行——对于刚开始使用 Pandas 的人来说,这通常会非常令人困惑,但过一段时间后就会变得很自然。(请记住,在方括号内使用单个列名会生成一列,而在方括号内使用切片会生成一行或多行。)

因此,要查看前十行,您可以说


df[:10]

当然,如果您只对查看进入服务器的前十个 HTTP 请求感兴趣,那么您可以说


df.r[:10]

当您从数据帧中请求单个列时,您实际上获得的是一个 Pandas 序列,它具有所有功能。

您通常想要对数据帧执行的操作之一是找出最受欢迎的数据。当处理日志文件时尤其如此,日志文件应该让您深入了解您的工作。例如,您可能想找出哪些 URL 最受欢迎。您可以要求计算 df 中的所有行


df.count()

这将为您提供所有行的总数。但是,您也可以检索单个列(这是一个 Pandas 序列)并要求它计算每个值出现的次数


df['r'].value_counts()

生成的序列具有作为值(即 URL)本身的索引,以及每个值出现的次数的计数(降序排列)。

绘图

这已经很棒了,但您可以做得更好并绘制结果。例如,您可能想要有一个条形图,指示前十个 URL 中每个 URL 被调用的次数。您可以说


df['r'].value_counts()[:10].plot.bar()

请注意,您如何获取原始数据帧,计算每个值出现的次数,取前十个值,然后通过 Matplotlib 调用绘图方法,生成一个简单但有效的条形图。如果您使用的是 Jupyter 并调用了 %pylab inline,这实际上会出现在您的浏览器窗口中,而不是外部程序中。

您也可以类似地制作饼图


df['r'].value_counts()[:10].plot.pie()

但是等一下。此图表表明,最受欢迎的 URL 是 /feed/,RSS 阅读器使用该 URL 来访问我的博客。虽然这很令人高兴,但它掩盖了我感兴趣的其他数据。因此,您可以使用“布尔索引”从 df 中检索行子集,然后仅绘制这些行


df[~df.r.str.contains('/feed/')]['r'].value_counts()[:10].plot.pie()

哇……这看起来既庞大又复杂。让我们把它分解开来,了解发生了什么

  • 这使用了布尔索引来检索某些行并删除其他行。条件是使用通用 Python 和 NumPy/Pandas 特定的语法和代码的组合来表达的。

  • 此示例使用了 Pandas 提供的 str.contains 方法,该方法使您能够查找 URL 包含 “/feed/” 的所有行。

  • 然后,该示例使用了(通常的)按位运算符 ~ 来反转您尝试查找的逻辑。

  • 最后,绘制结果,提供哪些 URL 受欢迎和不受欢迎的图片。

从 CSV 读取数据并将其读入数据帧,可以在操作数据以及最终绘制数据时提供极大的灵活性。

结论

在本文中,我描述了如何将日志文件数据读入 Pandas,甚至使用它执行了一些小型绘图。在未来的文章中,我计划解释如何进一步转换数据,以便为每个对日志文件感兴趣的人提供见解。

资源

数据科学是一个热门话题,许多人一直在撰写关于该主题的好书。我最近一直在阅读并欣赏 Jake VanderPlas 的Python Data Science Handbook的早期版本,其中包含关于数据科学及其在 Python 中的应用的精彩信息。Cathy O'Neil 和 Rachel Schutt 稍早的书籍Doing Data Science也很出色,它们从不同的角度处理问题。这两本书均由 O'Reilly 出版,如果您对数据科学感兴趣,这两本书都值得一读。

要了解有关数据科学中使用的 Python 工具的更多信息,请查看 NumPy、SciPyPandasIPython 的站点。有很多东西要学习,所以要准备好深入研究和大量阅读。

Pandas 可从 https://pandas.ac.cn 获取,并在该站点上提供文档。

Python 本身可从 这里 获取,PyPI 软件包索引(您可以从中下载本文中提到的所有软件包)位于 这里

Reuven Lerner 在世界各地的公司教授 Python、数据科学和 Git。您可以订阅他的免费、每周“更好的开发者”电子邮件列表,并从他的书籍和课程中学习,网址为 http://lerner.co.il。Reuven 与他的妻子和孩子住在以色列的 Modi'in。

加载 Disqus 评论