本书涉及在Python中的数据操作、处理、清洗和处理的具体细节。我们的目标是为Python编程语言及其面向数据的库生态系统和工具的各个部分提供指南,让你成为一名高效的数据分析师。虽然“数据分析”是本书的标题,但重点是Python编程、库和工具,而不是数据分析方法。这是数据分析所需要的Python编程。
在我最初于2012年出版这本书后的某个时刻,人们开始用数据科学这个术语作为从简单的描述性统计到更高级的统计分析和机器学习等的一切总括性描述。从那时起,用于进行数据分析的Python开源生态系统也得到了显著扩展。现在有很多其他书籍专注于这些更高级的方法。我希望本书能为你进入一个具体的领域做好充分的准备。
当我说“数据”时,我到底指的是什么?主要重点是结构化数据,这是一个特意模糊的术语,包含许多不同的常见数据形式,例如:
这绝不是一个完整的列表。尽管可能并不总是很明显,但很大一部分数据集可以转换为更适合分析和建模的结构化形式。如果没有,则可以将数据集中的特征提取为结构化形式。例如,可以将一组新闻文章处理成词频表,然后可以将其用于执行情感分析。
Microsoft Excel等电子表格程序(可能是世界上使用最广泛的数据分析工具)的大多数用户对这类数据并不陌生。
对于很多人来说,Python编程语言具有很强的吸引力。自1991年首次出现以来,Python已与Perl、Ruby等一起成为最流行的解释型编程语言之一。自2005年左右以来,Python和 Ruby在使用其众多Web框架(如Rails(Ruby)和Django (Python)构建网站时变得特别流行。这种语言通常被称为脚本语言,因为它们可以用来快速编写小程序或脚本自动化其他任务。我不喜欢“脚本语言”这个术语,因为它带有一种含义,即它们不能用于构建严肃的软件。在解释性语言中,由于各种历史和文化原因,Python发展了一个庞大而活跃的科学计算和数据分析社区。在过去的 20 年中,Python已经从一种前沿或“风险自负”的科学计算语言发展成为学术界和工业界数据科学、机器学习和通用软件开发最重要的语言之一。
在数据分析和交互式计算以及数据可视化方面,Python不可避免地会与其他广泛使用的开源和商业编程语言和工具进行比较,例如R、MATLAB、SAS、Stata等。近年来,Python改进的开源库(如pandas和scikit-learn)使其成为数据分析任务的热门选择。结合Python在通用软件工程方面的整体实力,它是构建数据应用程序的主要语言的绝佳选择。
Python在科学计算方面的成功是它易于集成C、C++和FORTRAN代码。大多数现代计算环境共享一组相似的传统FORTRAN 和C库,用于执行线性代数、优化、集成、快速傅立叶变换和其他此类算法。对于许多使用Python将数十年的遗留软件粘合在一起的公司和国家实验室来说,同样的情况也是如此。
许多程序由花费大部分时间的小部分代码和大量不经常运行的“粘合代码”组成。在很多情况下,胶水代码的执行时间是微不足道的;努力在优化计算瓶颈方面最有成效,有时是通过将代码移至C等较低级别的语言。
在许多组织中,通常使用 SAS 或 R 等更专业的计算语言来研究、原型化和测试新想法,然后将这些想法移植到用 Java、C# 或C++。人们越来越多地发现,Python 不仅适合进行研究和原型设计,而且适合构建生产系统。当一个就足够时,为什么要维护两个开发环境?我相信越来越多的公司会走这条路,因为让研究人员和软件工程师使用同一套编程工具通常会给组织带来巨大的好处。
在过去的十年中,出现了一些解决“双语”问题的新方法,例如 Julia 编程语言。在许多情况下,充分利用 Python需要使用 C 或 C++ 等低级语言进行编程,并创建与该代码的 Python 绑定。也就是说,Numba 等库提供的“即时”(JIT) 编译器技术提供了一种在许多计算算法中实现出色性能的方法,而无需离开 Python 编程环境。
虽然 Python 是构建多种分析应用程序和通用系统的绝佳环境,但 Python 可能不太适合许多用途。
由于 Python 是一种解释型编程语言,通常大多数 Python 代码的运行速度要比使用 Java 或 C++ 等编译语言编写的代码慢得多。由于程序员的时间通常比CPU 时间更有价值,因此许多人乐于做出这种权衡。然而,在具有极低延迟或苛刻的资源利用需求的应用程序中(例如,高频交易系统)中,花费时间在 C++ 等较低级别(但生产力也较低)的语言中编程以实现最大可能性能也许是值得的。
对于构建高度并发的多线程应用程序,尤其是具有许多 CPU 绑定线程的应用程序,Python 可能是一种具有挑战性的语言。原因是它具有所谓的全局解释器锁(GIL),这是一种防止解释器一次执行多个 Python 指令的机制。GIL 存在的技术原因超出了本书的范围。虽然在许多大数据处理应用程序中,可能需要一组计算机在合理的时间内处理数据集,但仍然存在需要单进程、多线程系统的情况。
这并不是说 Python 不能执行真正的多线程并行代码。使用本机多线程(在 C 或 C++ 中)的 Python C 扩展可以并行运行代码而不受 GIL 的影响,只要它们不需要定期与 Python 对象交互。
对于那些不太熟悉 Python 数据生态系统和本书中使用的库的人,我将简要概述其中的一些。
NumPy是 Numerical Python 的缩写,长期以来一直是 Python 中数值计算的基石。它提供了大多数涉及 Python 中数值数据的科学应用程序所需的数据结构、算法和库粘合剂。NumPy 包含以下内容:
除了 NumPy 为 Python 添加的快速数组处理功能之外,它在数据分析中的主要用途之一是作为在算法和库之间传递数据的容器。对于数值数据,NumPy 数组在存储和操作数据方面比其他内置 Python 数据结构更有效。此外,用 C 或 FORTRAN 等低级语言编写的库可以对存储在 NumPy 数组中的数据进行操作,而无需将数据复制到其他内存表示中。因此,许多 Python 数值计算工具要么将 NumPy 数组假定为主要数据结构,要么以与 NumPy 的互操作性为目标。
pandas提供了高级数据结构和函数,旨在使结构化或表格数据的处理变得直观和灵活。自 2010 年出现以来,它帮助 Python 成为一个强大且高效的数据分析环境。本书中使用的 pandas 中的主要对象是 DataFrame,一个表格的、面向列的数据结构,带有行和列标签,以及 Series,一个一维标签的数组对象。
pandas 将 NumPy 的数组计算思想与电子表格和关系数据库(如 SQL)中的各种数据操作功能相结合。它提供了方便的索引功能,使您能够重塑、切片和切块、执行聚合以及选择数据子集。由于数据操作、准备和清理是数据分析中如此重要的技能,pandas 是本书的主要关注点之一。
作为背景知识,我于 2008 年初在量化投资管理公司 AQR Capital Management 任职期间开始构建 pandas。当时,我有一组独特的需求,我可以使用的任何单一工具都无法很好地解决这些需求:
我希望能够在一个地方完成所有这些事情,最好是使用一种非常适合通用软件开发的语言。Python 是一个很好的候选语言,但当时不存在提供此功能的集成数据结构和工具集。由于最初是为解决财务和业务分析问题而构建的,pandas 具有特别深的时间序列功能和工具,非常适合处理业务流程生成的时间索引数据。
在 2011 年和 2012 年的大部分时间里,我与我的一些前 AQR 同事 Adam Klein 和 Chang She 一起扩展了 pandas 的功能。2013 年,我不再参与日常项目开发,pandas 已经成为一个完全由社区拥有和由社区维护的项目,在全球拥有超过 2000 名独特的贡献者。
对于使用 R 语言进行统计计算的用户来说,DataFrame 名称会很熟悉,因为对象是以相似的 R 对象命名的data.frame。与 Python 不同,数据帧内置于 R 编程语言及其标准库中。因此,pandas 中的许多功能通常要么是 R 核心实现的一部分,要么由附加包提供。
pandas 的名字本身来源于面板数据,一个多维结构化数据集的计量经济学术语,以及Python 数据分析这个短语。
matplotlib是最流行的 Python 库,用于生成绘图和其他二维数据可视化。它最初由 John D. Hunter 创建,现在由一个庞大的开发团队维护。它旨在创建适合出版的情节。虽然 Python 程序员可以使用其他可视化库,但 matplotlib 仍然被广泛使用,并且与生态系统的其他部分集成得相当好。我认为它作为默认的可视化工具是一个安全的选择。
IPython 项目始于 2001 年,是 Fernando Pérez 的副项目,目的是制作更好的交互式 Python 解释器。在随后的 20 年中,它已成为现代 Python 数据堆栈中最重要的工具之一。虽然它本身不提供任何计算或数据分析工具,但 IPython 是为交互式计算和软件开发工作而设计的。它鼓励执行-探索工作流程,而不是典型的编辑-编译-运行许多其他编程语言的工作流程。它还提供对操作系统外壳和文件系统的集成访问;这减少了在许多情况下在终端窗口和 Python 会话之间切换的需要。由于大部分数据分析编码都涉及探索、试错和迭代,因此 IPython 可以帮助您更快地完成工作。
2014 年,Fernando 和 IPython 团队宣布了Jupyter 项目,这是一项旨在设计与语言无关的交互式计算工具的更广泛的计划。IPython web notebook 变成了 Jupyter notebook,现在支持超过 40 种编程语言。IPython 系统现在可以用作内核(一种编程语言模式),以便将 Python 与 Jupyter 结合使用。
IPython 本身已成为更广泛的 Jupyter 开源项目的一个组件,该项目为交互式和探索性计算提供了一个生产环境。它最古老和最简单的“模式”是一种增强的 Python shell,旨在加速 Python 代码的编写、测试和调试。您还可以通过 Jupyter notebook 使用 IPython 系统。
Jupyter 笔记本系统还允许您使用 Markdown 和 HTML 创作内容,为您提供一种使用代码和文本创建丰富文档的方法。
我个人经常在我的 Python 工作中使用 IPython 和 Jupyter,无论是运行、调试还是测试代码。
在GitHub 上随附的书籍材料中,您将找到 Jupyter 笔记本,其中包含每章中的所有代码示例。如果你无法访问你所在的 GitHub,你可以试试 Gitee 上的镜像。
SciPy是解决科学计算中许多基本问题的软件包的集合。以下是它包含在其各个模块中的一些工具:
scipy.integrate
数值积分车程序和微分方程求解器
scipy.linalg
线性代数程序和矩阵分解,超越在numpy.linalg中所提供的
scipy.optimize
函数优化器(最小化器)和求根算法
scipy.signal
信号处理工具
scipy.sparse
稀疏矩阵和稀疏线性系统求解器
scipy.special
SPECFUN 的封装,一个 FORTRAN 库,实现了许多常见的数学函数,例如gamma函数
scipy.stats
标准的连续和离散概率分布(密度函数、采样器、连续分布函数)、各种统计检验和更多描述性统计
NumPy 和 SciPy 一起为许多传统的科学计算应用程序构成了一个相当完整和成熟的计算基础。
自 2007 年项目启动以来,scikit-learn已成为 Python 程序员首要的通用机器学习工具包。在撰写本文时,已有超过 2,000 名不同的人为该项目贡献了代码。它包括以下模型的子模块:
与 pandas、statsmodels 和 IPython 一起,scikit-learn 对于使 Python 成为一种高效的数据科学编程语言至关重要。虽然我无法在本书中包含全面的 scikit-learn 指南,但我将简要介绍它的一些模型以及如何将它们与书中介绍的其他工具一起使用。
statsmodels是一个统计分析包,由斯坦福大学统计学教授乔纳森·泰勒(Jonathan Taylor)的工作奠基,他实现了许多在 R 编程语言中流行的回归分析模型。Skipper Seabold 和 Josef Perktold 于 2010 年正式创建了新的 statsmodels 项目,并从那时起将该项目发展为拥有大量参与的用户和贡献者。Nathaniel Smith 开发了 Patsy 项目,该项目为受 R 公式系统启发的 statsmodels 提供公式或模型规范框架。
与 scikit-learn 相比,statsmodels 包含用于经典(主要是频率学派)统计和计量经济学的算法。这包括以下子模块:
statsmodels 更专注于统计推断,为参数提供不确定性估计和p值。相比之下,scikit-learn 更侧重于预测。
与 scikit-learn 一样,我将简要介绍 statsmodels 以及如何将其与 NumPy 和 pandas 一起使用。
在 2022 年,还有许多其他 Python 库可能会在一本关于数据科学的书中进行讨论。这包括一些较新的项目,如 TensorFlow 或 PyTorch,它们在机器学习或人工智能工作中变得很流行。现在还有其他书籍更专注于这些项目,我建议使用这本书来为通用 Python 数据整理打下基础。然后,您应该做好充分准备,转向可能具有一定专业知识水平的更高级的资源。
由于每个人都将 Python 用于不同的应用程序,因此没有单一的解决方案来设置 Python 并获得必要的附加包。很多读者不会有一个完整的 Python 开发环境适合跟随本书学习,所以在这里我将详细说明如何在每个操作系统上进行设置。我将使用 Miniconda,一个 conda 包管理器的最小安装,以及 conda - forge,一个基于 conda的社区维护的软件发行版。本书自始至终都使用 Python 3.10,但如果你是以后阅读本文,欢迎你安装更新版本的 Python。
如果由于某种原因这些说明在您阅读本文时已过时,您可以查看我的网站,我将努力与最新的安装说明保持同步。
为了在 Windows 上开始,请从https://conda.io下载最新可用的 Python 版本(当前为 3.9)的 Miniconda 安装程序。我建议按照 conda 网站上提供的 Windows 安装说明进行操作,这可能在本书出版和你阅读本书之间发生了变化。大多数人会想要 64 位版本,但如果它不能在你的 Windows 机器上运行,你可以安装 32 位版本。
当系统提示你是为你自己还是为系统上的所有用户安装时,请选择最适合你的选项。只为自己安装就足以与本书一起学习。它还会询问你是否要将 Miniconda 添加到系统 PATH 环境变量中。如果你选择这个(我通常这样做),那么这个 Miniconda 安装可能会覆盖你安装的其他 Python 版本。如果您不这样做,那么您将需要使用已安装的 Window Start 菜单快捷方式才能使用此 Miniconda。此开始菜单条目可能称为“Anaconda3(64 位)”。
我假设你尚未将 Miniconda 添加到系统 PATH 中。要验证配置是否正确,请在“开始”菜单中的“Anaconda3(64 位)”下打开“Anaconda Prompt (Miniconda3)”条目。然后尝试通过键入来启动 Python 解释器python。您应该会看到如下消息:
(base) C:\Users\Wes>python
Python 3.9 [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
要退出 Python shell,请键入exit()并按 Enter。
Linux 详细信息会因您的 Linux 发行版类型而有所不同,但在这里我会提供 Debian、Ubuntu、CentOS 和 Fedora 等发行版的详细信息。设置与 macOS 类似,但 Miniconda 的安装方式不同。大多数读者都希望下载默认的 64 位安装程序文件,它适用于 x86 架构(但未来可能会有更多用户拥有基于 aarch64 的 Linux 机器)。安装程序是一个必须在终端中执行的 shell 脚本。然后,您将拥有一个类似于Miniconda3-latest-Linux-x86_64.sh的文件。要安装它,请使用以下命令执行此脚本bash:
$ bash Miniconda3-latest-Linux-x86_64.sh
您可以选择放置 Miniconda 文件的位置。我建议将文件安装在主目录的默认位置;例如,/home/$USER/miniconda(当然是你的用户名)。
安装程序将询问您是否希望修改您的 shell 脚本以自动激活 Miniconda。为方便起见,我建议这样做(选择“是”)。
完成安装后,启动一个新的终端进程并确认您正在选择新的 Miniconda 安装:
(base) $ python
Python 3.9 | (main) [GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
要退出 Python shell,请键入exit()并按 Enter 或按 Ctrl-D。
下载 macOS Miniconda 安装程序,对于 2020 年以后发布的基于 Apple Silicon 的 macOS 计算机,该安装程序应命名为Miniconda3-latest-MacOSX-arm64.sh ,对于之前发布的基于 Intel 的 Mac计算机应命名为Miniconda3-latest-MacOSX-x86_64.sh 2020. 在 macOS 中打开终端应用程序,并通过执行安装程序(很可能在您的Downloads目录中)进行安装bash:
$ bash /Users/$USER/Miniconda3-latest-Linux-arm64.sh
当安装程序运行时,默认情况下它会在默认 shell 配置文件中的默认 shell 环境中自动配置 Miniconda。这可能位于/Users/$USER/.zshrc。我建议让它这样做;如果您不想让安装程序修改您的默认 shell 环境,则需要查阅 Miniconda 文档才能继续。
要验证一切正常,请尝试在系统 shell 中启动 Python(打开终端应用程序以获取命令提示符):
$ python
Python 3.9 (main) [Clang 12.0.1 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
要退出 shell,请按 Ctrl-D 或键入exit()并按 Enter。
现在我们已经在你的系统上设置了 Miniconda,是时候安装我们将在本书中使用的主要包了。第一步是通过在 shell 中运行以下命令将 conda-forge 配置为默认包通道:
(base) $ conda config --add channels conda-forge
(base) $ conda config --set channel_priority strict
现在,我们将使用 Python 3.10的“conda create”命令创建一个新的 conda“环境” :
(base) $ conda create -y -n pydata-book python=3.10
安装完成后,用“conda activate”激活环境:
(base) $ conda activate pydata-book
(pydata-book) $
⚠️每次打开新终端时,都需要用“conda activate”来激活你的环境。你可以通过运行“conda info”来随时查看激活的conda环境的信息
现在,我们将使用“conda install”命令安装本书中使用的基本包(以及它们的依赖项):
(pydata-book) $ conda install -y pandas jupyter matplotlib
我们也将使用其他一些软件包,但这些可以在以后需要时安装它们。有两种安装包的方法: 通过“conda install”命令和 通过“pip install”命令。当使用 Miniconda 时,应始终首选“conda install”命令,但某些包无法通过 conda 获得,因此如果“conda install $package_name”失败,请尝试“pip install $package_name”.
⚠️如果你想安装本书其余部分使用的所有包,你现在可以通过运行(在 Windows 上,在Linux 和 macOS 系统上用^ 续行符\):
conda install lxml beautifulsoup4 html5lib openpyxl \
requests sqlalchemy seaborn scipy statsmodels \
patsy scikit-learn pyarrow pytables numba
你可以使用“conda update”命令更新包:
conda update package_name
pip也支持使用“--upgrade”标记进行升级:
pip install --upgrade package_name
⚠️虽然您可以同时使用 conda 和 pip 来安装软件包,但您应该避免使用 pip 更新最初使用 conda 安装的软件包(反之亦然),因为这样做会导致环境问题。如果可以的话,我建议坚持使用 conda,并且只对使用“conda install”无法安装的包使用“pip”命令。
当被问及我的标准开发环境时,我几乎总是说“IPython 加上一个文本编辑器”。我通常编写一个程序,并在 IPython 或 Jupyter 笔记本中迭代地测试和调试它的每一部分。能够交互式地处理数据并直观地验证一组特定的数据操作是否在做正确的事情也很有用。像 pandas 和 NumPy 这样的库被设计成可以在 shell 中高效使用。
然而,在构建软件时,一些用户可能更喜欢使用功能更丰富的集成开发环境 (IDE),而不是像 Emacs 或 Vim 这样提供开箱即用的最小环境的编辑器。以下是您可以探索的一些内容:
PyDev(免费),基于 Eclipse 平台构建的 IDE
来自 JetBrains 的 PyCharm(商业用户基于订阅,开源开发者免费)
适用于 Visual Studio 的 Python 工具(适用于 Windows 用户)
Spyder(免费),当前随 Anaconda 一起提供的 IDE
Komodo IDE(商业)
由于 Python 的流行,大多数文本编辑器,如 VS Code 和 Sublime Text 2,都具有出色的 Python 支持。
在互联网搜索之外,各种与科学和数据相关的 Python 邮件列表通常对问题很有帮助和响应。一些值得一看的包括:
我故意不发布这些 URL,以防它们发生变化。它们可以通过互联网搜索轻松找到。
每年世界各地都会为 Python 程序员举办许多会议。如果您想与其他志趣相投的 Python 程序员交流,我鼓励您尽可能多地参加。许多会议为那些负担不起入场费或旅行费用的人提供财政支持。以下是一些需要考虑的因素:
如果您以前从未使用过 Python 编程,那么您将需要花一些时间阅读第2 章:“Python 语言基础、IPython 和 Jupyter Notebooks” 和第 3 章:“内置数据结构、函数和文件”,我在其中放置了一个关于 Python 语言功能以及 IPython shell 和 Jupyter 笔记本的简明教程。这些是本书其余部分的必备知识。如果您已经有 Python 经验,则可以选择略读或跳过这些章节。
接下来,我将简要介绍 NumPy 的主要特性,将更高级的 NumPy 使用留给“附录 A:高级 NumPy”。然后,我介绍了 pandas,并将本书的其余部分用于应用 pandas、NumPy 和 matplotlib(用于可视化)的数据分析主题。我以渐进的方式组织了材料,尽管章节之间偶尔会有一些小的交叉,在一些情况下使用了尚未介绍的概念。
虽然读者的工作可能有许多不同的最终目标,但所需的任务通常分为许多不同的大类:
读取和写入各种文件格式和数据存储
清理、整理、组合、规范化、重塑、切片和切块,以及转换数据以进行分析
将数学和统计运算应用于数据集组以派生新数据集(例如,按组变量聚合大表)
将您的数据连接到统计模型、机器学习算法或其他计算工具
创建交互式或静态图形可视化或文本摘要
本书中的大多数代码示例都显示了输入和输出,就像在 IPython shell 或 Jupyter 笔记本中执行时一样:
In [5]: CODE EXAMPLE
Out[5]: OUTPUT
当您看到这样的代码示例时,目的是让您In在编码环境的块中键入示例代码,然后按 Enter 键(或 Jupyter 中的 Shift-Enter)执行它。您应该看到类似于Out块中显示的输出。
我更改了 NumPy 和 pandas 中的默认控制台输出设置,以提高整本书的可读性和简洁性。例如,您可能会看到在数字数据中打印的精度位数更多。为了与书中显示的输出完全匹配,您可以在运行代码示例之前执行以下 Python 代码:
import numpy as np
import pandas as pd
pd.options.display.max_columns = 20
pd.options.display.max_rows = 20
pd.options.display.max_colwidth = 80
np.set_printoptions(precision=4, suppress=True)
每章中示例的数据集都托管在GitHub 存储库中(如果您无法访问 GitHub ,则托管在Gitee 上的镜像中)。您可以通过在命令行上使用 Git 版本控制系统或通过从网站下载存储库的 zip 文件来下载此数据。如果遇到问题,请导航至图书网站以获取有关获取图书资料的最新说明。
如果您下载包含示例数据集的 zip 文件,则必须将 zip 文件的内容完全解压缩到一个目录并从终端导航到该目录,然后再继续运行本书的代码示例:
$ pwd
/home/wesm/book-materials
$ ls
appa.ipynb ch05.ipynb ch09.ipynb ch13.ipynb README.md
ch02.ipynb ch06.ipynb ch10.ipynb COPYING requirements.txt
ch03.ipynb ch07.ipynb ch11.ipynb datasets
ch04.ipynb ch08.ipynb ch12.ipynb examples
Python 社区为常用模块采用了许多命名约定:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import statsmodels as sm
这意味着当您看到np.arange时,这是对NumPy中的arange函数的引用。这样做是因为在 Python 软件开发中,从 NumPy 之类的大包中导入所有内容 ( from numpy import *) 被认为是不好的做法。