Pandas-2-2-中文文档-一-

Pandas 2.2 中文文档(一)

原文:pandas.pydata.org/docs/

入门指南

原文:pandas.pydata.org/docs/getting_started/index.html

安装

使用 conda?

pandas 是Anaconda发行版的一部分,可以使用 Anaconda 或 Miniconda 进行安装:

conda  install  -c  conda-forge  pandas 

更喜欢 pip 吗?

可以通过 pip 从PyPI安装 pandas。

pip  install  pandas 

深入的说明?

想要安装特定版本?从源代码安装?请查看高级安装页面。

了解更多

pandas 简介

pandas 处理什么类型的数据?直达教程…

在处理表格数据(如存储在电子表格或数据库中的数据)时,pandas 是您的正确工具。pandas 将帮助您探索、清理和处理数据。在 pandas 中,数据表称为DataFrame

../_images/01_table_dataframe.svg 到介绍教程 到用户指南 如何读取和写入表格数据?直达教程…

pandas 原生支持与许多文件格式或数据源的集成(csv、excel、sql、json、parquet 等)。从每个数据源导入数据的功能由具有前缀read_*的函数提供。类似地,to_*方法用于存储数据。

../_images/02_io_readwrite.svg 到介绍教程 到用户指南 如何选择表的子集?直达教程…

需要选择或过滤特定行和/或列?根据条件过滤数据?pandas 提供了用于切片、选择和提取所需数据的方法。

../_images/03_subset_columns_rows.svg 到介绍教程 到用户指南 如何在 pandas 中创建图表?直达教程…

pandas 可以直接绘制您的数据,使用 Matplotlib 的强大功能。您可以选择与您的数据相对应的绘图类型(散点图、柱状图、箱线图等)。

../_images/04_plot_overview.svg 到介绍教程 到用户指南 如何根据现有列创建新列?直达教程…

没有必要遍历数据表的所有行来进行计算。对列的数据操作是逐个元素进行的。根据其他列中的现有数据向DataFrame添加列非常简单。

../_images/05_newcolumn_2.svg 进入教程 进入用户指南 如何计算摘要统计量? 直接到教程…

基本统计量(均值、中位数、最小值、最大值、计数等)很容易计算。这些统计量或自定义的聚合可以应用于整个数据集、数据的滑动窗口,或者按类别分组。后者也被称为分拆-应用-合并方法。

../_images/06_groupby.svg 进入教程 进入用户指南 如何改变表格的布局? 直接到教程…

在多种方式下改变数据表的结构。您可以将数据表从宽格式转换为长格式或整洁格式进行melt(),或者从长格式转换为宽格式进行pivot()。带有内置聚合函数,可以使用单个命令创建透视表。

../_images/07_melt.svg 进入教程 进入用户指南 如何合并来自多个表的数据? 直接到教程…

可以沿着列或行方向连接多个表格,因为提供了类似数据库的连接/合并操作来组合多个数据表。

../_images/08_concat_row.svg 进入教程 进入用户指南 如何处理时间序列数据? 直接到教程…

pandas 对时间序列有很好的支持,并且拥有一套广泛的工具用于处理日期、时间和时间索引数据。

进入教程 进入用户指南 如何操作文本数据? 直接到教程…

数据集不仅包含数值数据。pandas 提供了广泛的函数来清理文本数据并从中提取有用信息。

进入介绍教程 进入用户指南 ## 来源…

你熟悉其他用于操作表格数据的软件吗?学习与你已经了解的软件相比较的 pandas 等效操作:

R 编程语言提供了data.frame数据结构和多个包,例如 tidyverse 使用并扩展data.frame以方便处理数据,类似于 pandas。

了解更多

已经熟悉SELECTGROUP BYJOIN等操作了吗?大多数这些 SQL 操作在 pandas 中都有对应的操作。

了解更多

STATA 统计软件套件中包含的data set与 pandas DataFrame 对应。许多来自 STATA 的操作在 pandas 中都有对应的操作。

了解更多

使用 Excel 或其他电子表格程序的用户会发现许多概念可以转移到 pandas。

了解更多

SAS 统计软件套件也提供了与 pandas DataFrame 对应的data set。此外,SAS 的向量化操作、过滤、字符串处理等操作在 pandas 中也有类似功能。

了解更多

教程

想要快速了解 pandas 功能,请参阅 10 分钟入门 pandas。

您还可以参考 pandas 的速查表,以获得关于使用 pandas 操纵数据的简明指南。

社区制作了各种在线教程。一些材料列在社区贡献的社区教程中。

安装

使用 conda?

pandas 是Anaconda发行版的一部分,可以使用 Anaconda 或 Miniconda 进行安装:

conda  install  -c  conda-forge  pandas 

偏好 pip?

可以通过 pip 从PyPI安装 pandas。

pip  install  pandas 

深入的说明?

安装特定版本?从源代码安装?查看高级安装页面。

了解更多

pandas 入门

pandas 处理什么类型的数据?直接进入教程…

当处理表格数据时,如存储在电子表格或数据库中的数据时,pandas 是您的正确工具。pandas 将帮助您探索、清理和处理您的数据。在 pandas 中,数据表被称为DataFrame

../_images/01_table_dataframe.svg 进入教程 查看用户指南 如何读取和写入表格数据?直达教程…

pandas 支持与许多文件格式或数据源的集成(csv、excel、sql、json、parquet 等)。从这些数据源导入数据由带有前缀read_*的函数提供。类似地,使用to_*方法来存储数据。

../_images/02_io_readwrite.svg 进入教程 查看用户指南 如何选择表格的子集?直达教程…

选择或过滤特定的行和/或列?在条件上过滤数据?在 pandas 中有用于切片、选择和提取所需数据的方法。

../_images/03_subset_columns_rows.svg 进入教程 查看用户指南 如何在 pandas 中创建图形?直达教程…

pandas 提供了直接绘制数据的功能,利用了 Matplotlib 的强大功能。你可以选择与你的数据相对应的图形类型(散点图、条形图、箱线图等)。

../_images/04_plot_overview.svg 进入教程 查看用户指南 如何根据现有列创建新列?直达教程…

不需要遍历数据表的所有行来进行计算。对列进行的数据操作是逐元素进行的。根据其他列中的现有数据添加列到DataFrame非常简单。

../_images/05_newcolumn_2.svg 进入教程 查看用户指南 如何计算汇总统计信息?直达教程…

基本统计(均值、中位数、最小值、最大值、计数等)可轻松计算。这些或自定义聚合可以应用于整个数据集、数据的滑动窗口,或按类别分组。后者也被称为拆分-应用-组合方法。

../_images/06_groupby.svg 进入教程介绍 进入用户指南 如何重塑表格布局? 直达教程…

以多种方式更改数据表的结构。你可以将你的数据表从宽格式转换为长/整洁格式(melt()),或者从长格式转换为宽格式(pivot())。内置的聚合函数可以一次性创建一个数据透视表。

../_images/07_melt.svg 进入教程介绍 进入用户指南 如何组合来自多个表格的数据? 直达教程…

多个表格可以沿列和行进行连接,就像数据库的连接/合并操作一样,提供了用于合并多个数据表的操作。

../_images/08_concat_row.svg 进入教程介绍 进入用户指南 如何处理时间序列数据? 直达教程…

pandas 对于时间序列具有很好的支持,并且有一套丰富的工具用于处理日期、时间和以时间为索引的数据。

进入教程介绍 进入用户指南 如何操作文本数据? 直达教程…

数据集不仅包含数值数据。pandas 提供了广泛的函数来清理文本数据,并从中提取有用信息。

进入教程介绍 进入用户指南 ## 从哪里来…

你是否熟悉其他用于操作表格数据的软件?学习与你已知软件相比的 pandas 等效操作:

R 编程语言提供了 data.frame 数据结构以及多个包,例如 tidyverse 使用并扩展了 data.frame,提供了类似于 pandas 的便捷数据处理功能。

了解更多

SELECTGROUP BYJOIN等已经很熟悉了吗?大多数这些 SQL 操作在 pandas 中都有对应的操作。

了解更多

STATA统计软件套件中包含的数据集对应于 pandas 的DataFrame。许多从 STATA 熟知的操作在 pandas 中都有对应的操作。

了解更多

Excel或其他电子表格程序的用户会发现,许多概念都可以转移到 pandas 中。

了解更多

SAS统计软件套件也提供了与 pandas 的DataFrame相对应的数据集。此外,SAS 的向量化操作、过滤、字符串处理等操作在 pandas 中也有类似的功能。

了解更多

教程

想要快速了解 pandas 功能,请参阅 10 分钟入门 pandas。

您也可以参考 pandas 的速查表,以获得使用 pandas 进行数据操作的简洁指南。

社区制作了各种在线教程。一些材料被列在社区贡献的社区教程中。

安装

原文:pandas.pydata.org/docs/getting_started/install.html

安装 pandas 的最简单方法是作为Anaconda发行版的一部分安装,这是一个用于数据分析和科学计算的跨平台发行版。Conda包管理器是大多数用户推荐的安装方法。

还提供了从源代码安装(#install-source)、从 PyPI 安装(#install-pypi)或安装开发版本(#install-dev)的说明。

Python 版本支持

官方支持 Python 3.9、3.10、3.11 和 3.12。

安装 pandas

使用 Anaconda 安装

对于新手用户,安装 Python、pandas 和构成PyData堆栈(SciPyNumPyMatplotlib等)的包的最简单方法是使用Anaconda,这是一个跨平台(Linux、macOS、Windows)的 Python 发行版,用于数据分析和科学计算。Anaconda 的安装说明在这里。 ### 使用 Miniconda 安装

对于有经验的 Python 用户,推荐使用Miniconda安装 pandas。Miniconda 允许您创建一个相对于 Anaconda 更小、独立的 Python 安装,并使用Conda包管理器安装其他包并为您的安装创建虚拟环境。Miniconda 的安装说明在这里

下一步是创建一个新的 conda 环境。conda 环境类似于一个允许您指定特定版本的 Python 和一组库的虚拟环境。从终端窗口运行以下命令。

conda  create  -c  conda-forge  -n  name_of_my_env  python  pandas 

这将创建一个仅安装了 Python 和 pandas 的最小环境。要进入这个环境,请运行。

source  activate  name_of_my_env
# On Windows
activate  name_of_my_env 
```  ### 从 PyPI 安装

可以通过 pip 从[PyPI](https://pypi.org/project/pandas)安装 pandas。

```py
pip  install  pandas 

注意

您必须拥有pip>=19.3才能从 PyPI 安装。

注意

建议从虚拟环境中安装和运行 pandas,例如,使用 Python 标准库的venv

pandas 也可以安装带有可选依赖项集以启用某些功能。例如,要安装带有读取 Excel 文件的可选依赖项的 pandas。

pip  install  "pandas[excel]" 

可以在依赖部分找到可以安装的全部额外功能列表。

处理 ImportError

如果遇到 ImportError,通常意味着 Python 在可用库列表中找不到 pandas。Python 内部有一个目录列表,用于查找软件包。您可以通过以下方式获取这些目录。

import sys
sys.path 

您可能遇到此错误的一种方法是,如果您的系统上安装了多个 Python,并且您当前使用的 Python 安装中没有安装 pandas,则可能会遇到此错误。在 Linux/Mac 上,您可以在终端上运行 which python,它将告诉您当前正在使用哪个 Python 安装。如果是类似“/usr/bin/python”的东西,则表示您正在使用系统中的 Python,这是不推荐的。

强烈建议使用 conda,以便快速安装和更新软件包和依赖项。您可以在此文档中找到有关 pandas 的简单安装说明。

从源代码安装

请参阅贡献指南以获取有关从 git 源代码树构建的完整说明。此外,如果您希望创建 pandas 开发环境,请参阅创建开发环境。 ### 安装 pandas 的开发版本

安装开发版本是最快的方法:

  • 尝试一个新功能,该功能将在下一个发布中发布(即,从最近合并到主分支的拉取请求中提取的功能)。

  • 检查您遇到的错误是否在上次发布之后修复。

开发版本通常每天上传到 anaconda.org 的 PyPI 注册表的 scientific-python-nightly-wheels 索引中。您可以通过运行以下命令进行安装。

pip  install  --pre  --extra-index  https://pypi.anaconda.org/scientific-python-nightly-wheels/simple  pandas 

请注意,您可能需要卸载现有版本的 pandas 才能安装开发版本。

pip  uninstall  pandas  -y 

运行测试套件

pandas 配备有一套详尽的单元测试。运行测试所需的软件包可以使用 pip install "pandas[test]" 进行安装。要从 Python 终端运行测试。

>>> import pandas as pd
>>> pd.test()
running: pytest -m "not slow and not network and not db" /home/user/anaconda3/lib/python3.9/site-packages/pandas

============================= test session starts ==============================
platform linux -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/user
plugins: dash-1.19.0, anyio-3.5.0, hypothesis-6.29.3
collected 154975 items / 4 skipped / 154971 selected
........................................................................ [  0%]
........................................................................ [ 99%]
.......................................                                  [100%]

==================================== ERRORS ====================================

=================================== FAILURES ===================================

=============================== warnings summary ===============================

=========================== short test summary info ============================

= 1 failed, 146194 passed, 7402 skipped, 1367 xfailed, 5 xpassed, 197 warnings, 10 errors in 1090.16s (0:18:10) = 

注意

这只是显示的信息示例。测试失败并不一定表示 pandas 安装有问题。

依赖项

必需的依赖项

pandas 需要以下依赖项。

软件包 最低支持版本
NumPy 1.22.4
python-dateutil 2.8.2
pytz 2020.1

| tzdata | 2022.7 | ### 可选依赖项

pandas 有许多可选依赖项,仅用于特定方法。例如,pandas.read_hdf() 需要 pytables 包,而 DataFrame.to_markdown() 需要 tabulate 包。如果未安装可选依赖项,则在调用需要该依赖项的方法时,pandas 将引发 ImportError

如果使用 pip,可选的 pandas 依赖项可以作为可选额外项(例如 pandas[performance, aws])安装或在文件中管理(例如 requirements.txt 或 pyproject.toml)。所有可选依赖项都可以通过 pandas[all] 安装,特定的依赖项集在下面的各节中列出。

性能依赖项(推荐)

注意

鼓励您安装这些库,因为它们提供了速度改进,特别是在处理大型数据集时。

可通过 pip install "pandas[performance]" 进行安装。

依赖项 最低版本 pip 额外 注释
numexpr 2.8.4 性能 通过使用多个核心以及智能分块和缓存来加速某些数值运算
bottleneck 1.3.6 性能 通过使用专门的 cython 程序加速某些类型的 nan,从而实现大幅加速。
numba 0.56.4 性能 用��接受 engine="numba" 的操作的替代执行引擎,使用 JIT 编译器将 Python 函数转换为优化的机器代码,使用 LLVM 编译器实现大幅优化。

可视化

可通过 pip install "pandas[plot, output-formatting]" 进行安装。

依赖项 最低版本 pip 额外 注释
matplotlib 3.6.3 绘图 绘图库
Jinja2 3.1.2 输出格式化 与 DataFrame.style 一起使用的条件格式化
tabulate 0.9.0 输出格式化 以 Markdown 友好的格式打印(参见 tabulate

计算

可通过 pip install "pandas[computation]" 进行安装。

依赖项 最低版本 pip 额外 注释
SciPy 1.10.0 计算 各种统计函数
xarray 2022.12.0 计算 用于 N 维数据的类似于 pandas 的 API

Excel 文件

可通过 pip install "pandas[excel]" 进行安装。

依赖项 最低版本 pip 额外 注释
xlrd 2.0.1 excel 读取 Excel
xlsxwriter 3.0.5 excel 写入 Excel
openpyxl 3.1.0 excel 读取/写入 xlsx 文件
pyxlsb 1.0.10 excel 读取 xlsb 文件
python-calamine 0.1.7 excel 读取 xls/xlsx/xlsb/ods 文件

HTML

可通过 pip install "pandas[html]" 进行安装。

依赖 最低版本 pip 额外组件 注释
BeautifulSoup4 4.11.2 html 用于 read_html 的 HTML 解析器
html5lib 1.1 html 用于 read_html 的 HTML 解析器
lxml 4.9.2 html 用于 read_html 的 HTML 解析器

使用顶层 read_html() 函数,需要以下库组合之一:

警告

  • 如果你安装了 BeautifulSoup4,你必须安装 lxml 或者 html5lib,或者两者都安装。只有安装了 BeautifulSoup4read_html() 才会 起作用。

  • 强烈建议阅读 HTML 表解析陷阱。它解释了上述三个库的安装和使用相关问题。

XML

通过 pip install "pandas[xml]" 安装。

依赖 最低版本 pip 额外组件 注释
lxml 4.9.2 xml read_xml 的 XML 解析器和 to_xml 的树生成器

SQL 数据库

传统驱动可以通过 pip install "pandas[postgresql, mysql, sql-other]" 安装。

依赖 最低版本 pip 额外组件 注释
SQLAlchemy 2.0.0 postgresql, mysql, sql-other 除 sqlite 外其他数据库的 SQL 支持
psycopg2 2.9.6 postgresql 用于 sqlalchemy 的 PostgreSQL 引擎
pymysql 1.0.2 mysql 用于 sqlalchemy 的 MySQL 引擎
adbc-driver-postgresql 0.8.0 postgresql PostgreSQL 的 ADBC 驱动程序
adbc-driver-sqlite 0.8.0 sql-other SQLite 的 ADBC 驱动程序

其他数据源

通过 pip install "pandas[hdf5, parquet, feather, spss, excel]" 安装。

依赖 最低版本 pip 额外组件 注释
PyTables 3.8.0 hdf5 基于 HDF5 的读取 / 写入
blosc 1.21.3 hdf5 HDF5 压缩;仅适用于 conda
zlib hdf5 HDF5 压缩
fastparquet 2022.12.0 Parquet 读取 / 写入(pyarrow 是默认)
pyarrow 10.0.1 parquet, feather Parquet、ORC 和 feather 读取 / 写入
pyreadstat 1.2.0 spss SPSS 文件(.sav)读取
odfpy 1.4.1 excel Open document format (.odf, .ods, .odt) 读取 / 写入

警告

  • 如果你想使用 read_orc(),强烈建议使用 conda 安装 pyarrow。如果 pyarrow 是从 pypi 安装的,可能会导致 read_orc() 失败,并且 read_orc() 与 Windows 操作系统不兼容。

访问云端数据

使用 pip install "pandas[fss, aws, gcp]" 可安装。

依赖 最低版本 pip 额外 注释
fsspec 2022.11.0 fss, gcp, aws 处理除简单本地和 HTTP 外的文件(s3fs、gcsfs 的必需依赖)。
gcsfs 2022.11.0 gcp 谷歌云存储访问
pandas-gbq 0.19.0 gcp 谷歌大数据查询访问
s3fs 2022.11.0 aws 亚马逊 S3 访问

剪贴板

使用 pip install "pandas[clipboard]" 可安装。

依赖 最低版本 pip 额外 注释
PyQt4/PyQt5 5.15.9 clipboard 剪贴板 I/O
qtpy 2.3.0 clipboard 剪贴板 I/O

注意

根据操作系统的不同,可能需要安装系统级软件包。在 Linux 上,要使剪贴板正常工作,必须安装其中一个命令行工具 xclipxsel

压缩

使用 pip install "pandas[compression]" 可安装。

依赖 最低版本 pip 额外 注释
Zstandard 0.19.0 compression Zstandard 压缩

联盟标准

使用 pip install "pandas[consortium-standard]" 可安装。

依赖 最低版本 pip 额外 注释

| dataframe-api-compat | 0.1.7 | consortium-standard | 基于 pandas 的联盟标准兼容实现 | ## Python 版本支持

官方支持 Python 3.9、3.10、3.11 和 3.12。

安装 pandas

使用 Anaconda 安装

对于新手用户,安装 Python、pandas 以及构成 PyData 栈(SciPyNumPyMatplotlib 等)的软件包最简单的方法是使用 Anaconda,这是一个跨平台(Linux、macOS、Windows)的数据分析和科学计算 Python 发行版。Anaconda 的安装说明 可在此找到。 ### 使用 Miniconda 安装

对于有 Python 经验的用户,推荐使用Miniconda安装 pandas。Miniconda 允许您创建一个最小的、独立的 Python 安装,与 Anaconda 相比,并使用Conda包管理器安装其他包并为您的安装创建虚拟环境。有关 Miniconda 的安装说明可以在这里找到

下一步是创建一个新的 conda 环境。conda 环境类似于一个允许您指定特定 Python 版本和一组库的虚拟环境。从终端窗口运行以下命令。

conda  create  -c  conda-forge  -n  name_of_my_env  python  pandas 

这将创建一个只安装了 Python 和 pandas 的最小环境。要进入此环境,请运行。

source  activate  name_of_my_env
# On Windows
activate  name_of_my_env 
```  ### 从 PyPI 安装

可以通过 pip 从[PyPI](https://pypi.org/project/pandas)安装 pandas。

```py
pip  install  pandas 

注意

您必须拥有pip>=19.3才能从 PyPI 安装。

注意

建议安装并从虚拟环境中运行 pandas,例如,使用 Python 标准库的venv

pandas 也可以安装一组可选依赖项,以启用某些功能。例如,要安装带有可选依赖项以读取 Excel 文件的 pandas。

pip  install  "pandas[excel]" 

可以在依赖部分找到可以安装的全部额外内容列表。

处理 ImportErrors

如果遇到ImportError,通常意味着 Python 在可用库列表中找不到 pandas。Python 内部有一个目录列表,用于查找包。您可以通过以下方式获取这些目录。

import sys
sys.path 

您可能遇到此错误的一种方式是,如果您的系统上有多个 Python 安装,并且您当前使用的 Python 安装中没有安装 pandas。在 Linux/Mac 上,您可以在终端上运行which python,它会告诉您正在使用哪个 Python 安装。如果类似于“/usr/bin/python”,则您正在使用系统中的 Python,这是不推荐的。

强烈建议使用conda进行快速安装和包和依赖项更新。您可以在此文档中找到有关 pandas 的简单安装说明。

从源代码安装

请查看贡献指南以获取有关从 git 源代码树构建的完整说明。此外,如果您希望创建 pandas 开发环境,请查看创建开发环境。 ### 安装 pandas 的开发版本

安装开发版本是最快的方法:

  • 尝试一个将在下一个发布中提供的新功能(即,最近合并到主分支的拉取请求中的功能)。

  • 检查您遇到的错误是否在上一个版本中已修复。

开发版本通常每天上传到 anaconda.org 的 PyPI 注册表的 scientific-python-nightly-wheels 索引中。您可以通过运行来安装它。

pip  install  --pre  --extra-index  https://pypi.anaconda.org/scientific-python-nightly-wheels/simple  pandas 

请注意,您可能需要卸载现有版本的 pandas 才能安装开发版本。

pip  uninstall  pandas  -y 
```  ### 使用 Anaconda 安装

对于新手用户,安装 Python、pandas 和构成[PyData](https://pydata.org/)堆栈([SciPy](https://scipy.org/)、[NumPy](https://numpy.org/)、[Matplotlib](https://matplotlib.org/)等)的包最简单的方法是使用[Anaconda](https://docs.continuum.io/free/anaconda/),这是一个跨平台(Linux、macOS、Windows)的用于数据分析和科学计算的 Python 发行版。有关 Anaconda 的安装说明[请参见此处](https://docs.continuum.io/free/anaconda/install/)。

### 使用 Miniconda 安装

对于有 Python 经验的用户,推荐使用[Miniconda](https://docs.conda.io/en/latest/miniconda.html)安装 pandas。Miniconda 允许您创建一个最小、独立的 Python 安装,与 Anaconda 相比,使用[Conda](https://conda.io/en/latest/)包管理器安装额外的包并为您的安装创建虚拟环境。有关 Miniconda 的安装说明[请参见此处](https://docs.conda.io/en/latest/miniconda.html)。

下一步是创建一个新的 conda 环境。conda 环境类似于一个允许您指定特定 Python 版本和一组库的虚拟环境。从终端窗口运行以下命令。

```py
conda  create  -c  conda-forge  -n  name_of_my_env  python  pandas 

这将创建一个只安装了 Python 和 pandas 的最小环境。要进入此环境,请运行。

source  activate  name_of_my_env
# On Windows
activate  name_of_my_env 

从 PyPI 安装

可以通过pip从 PyPI 安装 pandas。

pip  install  pandas 

注意

您必须拥有pip>=19.3才能从 PyPI 安装。

注意

建议在虚拟环境中安装和运行 pandas,例如,使用 Python 标准库的venv

pandas 也可以安装带有可选依赖项集合以启用某些功能。例如,要安装带有可选依赖项以读取 Excel 文件的 pandas。

pip  install  "pandas[excel]" 

可以在依赖部分找到可以安装的全部额外功能列表。

处理 ImportErrors

如果遇到ImportError,通常意味着 Python 在可用库列表中找不到 pandas。Python 内部有一个目录列表,用于查找包。您可以通过以下方式获取这些目录。

import sys
sys.path 

您可能遇到此错误的一种方式是,如果您的系统上有多个 Python 安装,并且您当前使用的 Python 安装中没有安装 pandas。在 Linux/Mac 上,您可以在终端上运行which python,它会告诉您当前使用的 Python 安装。如果显示类似“/usr/bin/python”的内容,则表示您正在使用系统中的 Python,这是不推荐的。

强烈建议使用conda,以快速安装和更新包和依赖项。您可以在此文档中找到 pandas 的简单安装说明。

从源代码安装

查看贡献指南以获取有关从 git 源代码树构建的完整说明。此外,如果您希望创建一个 pandas 开发环境,请查看创建开发环境。

安装 pandas 的开发版本

安装开发版本是最快的方式:

  • 尝试一个将在下一个版本中发布的新功能(即,最近合并到主分支的拉取请求中的功能)。

  • 检查您遇到的错误是否自上次发布以来已修复。

开发版本通常每天上传到 anaconda.org 的 PyPI 注册表的 scientific-python-nightly-wheels 索引中。您可以通过运行以下命令来安装。

pip  install  --pre  --extra-index  https://pypi.anaconda.org/scientific-python-nightly-wheels/simple  pandas 

请注意,您可能需要卸载现有版本的 pandas 才能安装开发版本。

pip  uninstall  pandas  -y 

运行测试套件

pandas 配备了一套详尽的单元测试。运行测试所需的包可以通过pip install "pandas[test]"安装。要从 Python 终端运行测试。

>>> import pandas as pd
>>> pd.test()
running: pytest -m "not slow and not network and not db" /home/user/anaconda3/lib/python3.9/site-packages/pandas

============================= test session starts ==============================
platform linux -- Python 3.9.7, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/user
plugins: dash-1.19.0, anyio-3.5.0, hypothesis-6.29.3
collected 154975 items / 4 skipped / 154971 selected
........................................................................ [  0%]
........................................................................ [ 99%]
.......................................                                  [100%]

==================================== ERRORS ====================================

=================================== FAILURES ===================================

=============================== warnings summary ===============================

=========================== short test summary info ============================

= 1 failed, 146194 passed, 7402 skipped, 1367 xfailed, 5 xpassed, 197 warnings, 10 errors in 1090.16s (0:18:10) = 

注意

这只是显示的信息示例。测试失败并不一定表示 pandas 安装有问题。

依赖关系

必需依赖

pandas 需要以下依赖项。

最低支持版本
NumPy 1.22.4
python-dateutil 2.8.2
pytz 2020.1

| tzdata | 2022.7 | ### 可选依赖

pandas 有许多可选依赖项,仅用于特定方法。例如,pandas.read_hdf()需要pytables包,而DataFrame.to_markdown()需要tabulate包。如果未安装可选依赖项,则在调用需要该依赖项的方法时,pandas 将引发ImportError

如果使用 pip,可以将可选的 pandas 依赖项安装或管理到文件中(例如 requirements.txt 或 pyproject.toml),作为可选的额外功能(例如 pandas[performance, aws])。所有可选依赖项均可使用 pandas[all] 安装,具体的依赖项集合列在下面的各个部分中。

性能依赖项(推荐)

注意

强烈建议您安装这些库,因为它们提供了速度改进,特别是在处理大数据集时。

使用 pip install "pandas[performance]" 进行安装

依赖项 最低版本 pip extra 注释
numexpr 2.8.4 performance 通过使用多个核心以及智能分块和缓存来加速某些数值运算。
bottleneck 1.3.6 performance 通过使用专门的 cython 程序加速某些类型的 nan,以实现大幅加速。
numba 0.56.4 performance 用于接受 engine="numba" 的操作的替代执行引擎,使用 JIT 编译器将 Python 函数转换为优化的机器码,使用 LLVM 编译器实现大幅度优化。

可视化

使用 pip install "pandas[plot, output-formatting]" 进行安装。

依赖项 最低版本 pip extra 注释
matplotlib 3.6.3 plot 绘图库
Jinja2 3.1.2 output-formatting 使用 DataFrame.style 进行条件格式化
tabulate 0.9.0 output-formatting 以 Markdown 友好的格式打印(参见 tabulate

计算

使用 pip install "pandas[computation]" 进行安装。

依赖项 最低版本 pip extra 注释
SciPy 1.10.0 computation 杂项统计函数
xarray 2022.12.0 computation 用于 N 维数据的类似 pandas API

Excel 文件

使用 pip install "pandas[excel]" 进行安装。

依赖项 最低版本 pip extra 注释
xlrd 2.0.1 excel 读取 Excel
xlsxwriter 3.0.5 excel 写入 Excel
openpyxl 3.1.0 excel 用于读取 / 写入 xlsx 文件
pyxlsb 1.0.10 excel 用于读取 xlsb 文件
python-calamine 0.1.7 excel 用于读取 xls/xlsx/xlsb/ods 文件

HTML

使用 pip install "pandas[html]" 进行安装。

依赖项 最低版本 pip extra 注释
BeautifulSoup4 4.11.2 html 用于 read_html 的 HTML 解析器
html5lib 1.1 html 用于 read_html 的 HTML 解析器
lxml 4.9.2 html 用于 read_html 的 HTML 解析器

若要使用顶层 read_html() 函数,需要以下其中一种组合的库:

警告

  • 如果安装了 BeautifulSoup4,您必须安装 lxmlhtml5lib 或两者都安装。只安装 BeautifulSoup4不会 使 read_html() 正常工作。

  • 强烈建议阅读 HTML 表格解析注意事项。它解释了关于上述三个库的安装和使用的问题。

XML

可通过 pip install "pandas[xml]" 进行安装。

依赖 最低版本 pip extra 注释
lxml 4.9.2 xml 用于 read_xml 的 XML 解析器,用于 to_xml 的树构建器

SQL 数据库

传统驱动程序可通过 pip install "pandas[postgresql, mysql, sql-other]" 进行安装。

依赖 最低版本 pip extra 注释
SQLAlchemy 2.0.0 postgresql, mysql, sql-other 除 sqlite 外的数据库的 SQL 支持
psycopg2 2.9.6 postgresql SQLAlchemy 的 PostgreSQL 引擎
pymysql 1.0.2 mysql SQLAlchemy 的 MySQL 引擎
adbc-driver-postgresql 0.8.0 postgresql 用于 PostgreSQL 的 ADBC 驱动程序
adbc-driver-sqlite 0.8.0 sql-other 用于 SQLite 的 ADBC 驱动程序

其他数据源

可通过 pip install "pandas[hdf5, parquet, feather, spss, excel]" 进行安装。

依赖 最低版本 pip extra 注释
PyTables 3.8.0 hdf5 基于 HDF5 的读取/写入
blosc 1.21.3 hdf5 HDF5 的压缩;仅在 conda 上可用
zlib hdf5 HDF5 的压缩
fastparquet 2022.12.0 Parquet 的读取/写入(pyarrow 是默认值)
pyarrow 10.0.1 parquet, feather Parquet、ORC 和 feather 的读取/写入
pyreadstat 1.2.0 spss SPSS 文件(.sav)的读取
odfpy 1.4.1 excel Open document format (.odf, .ods, .odt) 读取/写入

警告

  • 如果您想使用 read_orc(),强烈建议使用 conda 安装 pyarrow。如果从 pypi 安装了 pyarrow,read_orc() 可能会失败,并且 read_orc() 不兼容 Windows 操作系统。

访问云中的数据

可通过 pip install "pandas[fss, aws, gcp]" 进行安装。

依赖 最低版本 pip extra 注释
fsspec 2022.11.0 fss, gcp, aws 处理除简单本地和 HTTP 之外的文件(s3fs、gcsfs 的必需依赖)。
gcsfs 2022.11.0 gcp 谷歌云存储访问
pandas-gbq 0.19.0 gcp 谷歌 Big Query 访问
s3fs 2022.11.0 aws 亚马逊 S3 访问

剪贴板

可通过 pip install "pandas[clipboard]" 进行安装。

依赖 最低版本 pip 额外 注释
PyQt4/PyQt5 5.15.9 clipboard 剪贴板 I/O
qtpy 2.3.0 clipboard 剪贴板 I/O

注意

根据操作系统的不同,可能需要安装系统级软件包。在 Linux 上,剪贴板要正常运行,系统必须安装 xclipxsel 中的一个 CLI 工具。

压缩

可通过 pip install "pandas[compression]" 进行安装。

依赖 最低版本 pip 额外 注释
Zstandard 0.19.0 compression Zstandard 压缩

联盟标准

可通过 pip install "pandas[consortium-standard]" 进行安装。

依赖 最低版本 pip 额外 注释

| dataframe-api-compat | 0.1.7 | consortium-standard | 基于 pandas 的联盟标准兼容实现 | ### 必需依赖

pandas 需要以下依赖。

最低支持版本
NumPy 1.22.4
python-dateutil 2.8.2
pytz 2020.1
tzdata 2022.7

可选依赖

pandas 有许多仅用于特定方法的可选依赖。例如,pandas.read_hdf() 需要 pytables 包,而 DataFrame.to_markdown() 需要 tabulate 包。如果未安装可选依赖,当调用需要该依赖的方法时,pandas 将引发 ImportError

如果使用 pip,可选的 pandas 依赖可以作为可选额外项(例如 pandas[performance, aws])安装或管理在文件中(例如 requirements.txt 或 pyproject.toml),所有可选依赖可以通过 pandas[all] 进行安装,特定的依赖集在下面的部分中列出。

性能依赖(推荐)

注意

强烈建议安装这些库,因为它们提供了速度改进,特别是在处理大数据集时。

可通过 pip install "pandas[performance]" 进行安装。

依赖 最低版本 pip 额外 注释
numexpr 2.8.4 performance 通过使用多核心、智能分块和缓存来加速某些数值操作
bottleneck 1.3.6 performance 通过使用专门的 cython 程序加速某些类型的 nan,实现大幅加速。
numba 0.56.4 performance 用于接受 engine="numba" 的操作的替代执行引擎,使用 JIT 编译器将 Python 函数转换为优化的机器码,使用 LLVM 编译器。

可视化

可通过 pip install "pandas[plot, output-formatting]" 进行安装。

依赖 最低版本 pip 额外 备注
matplotlib 3.6.3 plot 绘图库
Jinja2 3.1.2 output-formatting 使用 DataFrame.style 进行条件格式化
tabulate 0.9.0 output-formatting 以 Markdown 友好格式打印(参见 tabulate

计算

可通过 pip install "pandas[computation]" 进行安装。

依赖 最���版本 pip 额外 备注
SciPy 1.10.0 computation 各种统计函数
xarray 2022.12.0 computation 用于 N 维数据的类似 pandas API

Excel 文件

可通过 pip install "pandas[excel]" 进行安装。

依赖 最低版本 pip 额外 备注
xlrd 2.0.1 excel Excel 读取
xlsxwriter 3.0.5 excel Excel 写入
openpyxl 3.1.0 excel 用于 xlsx 文件的读取/写入
pyxlsb 1.0.10 excel 用于 xlsb 文件的读取
python-calamine 0.1.7 excel 用于 xls/xlsx/xlsb/ods 文件的读取

HTML

可通过 pip install "pandas[html]" 进行安装。

依赖 最低版本 pip 额外 备注
BeautifulSoup4 4.11.2 html 用于 read_html 的 HTML 解析器
html5lib 1.1 html 用于 read_html 的 HTML 解析器
lxml 4.9.2 html 用于 read_html 的 HTML 解析器

使用顶层 read_html() 函数需要以下库中的一种或多种组合:

警告

  • 如果安装了 BeautifulSoup4,则必须安装 lxmlhtml5lib 或两者都安装。仅安装 BeautifulSoup4 不会 使 read_html() 起作用。

  • 强烈建议阅读 HTML Table Parsing gotchas。它解释了关于安装和使用上述三个库的问题。

XML

使用 pip install "pandas[xml]" 可以安装。

依赖 最低版本 pip 额外 注释
lxml 4.9.2 xml 用于 read_xml 的 XML 解析器和用于 to_xml 的树生成器

SQL 数据库

传统驱动程序可以使用 pip install "pandas[postgresql, mysql, sql-other]" 进行安装。

依赖 最低版本 pip 额外 注释
SQLAlchemy 2.0.0 postgresql, mysql, sql-other 除了 sqlite 外其他数据库的 SQL 支持
psycopg2 2.9.6 postgresql SQLAlchemy 的 PostgreSQL 引擎
pymysql 1.0.2 mysql SQLAlchemy 的 MySQL 引擎
adbc-driver-postgresql 0.8.0 postgresql 用于 PostgreSQL 的 ADBC 驱动程序
adbc-driver-sqlite 0.8.0 sql-other 用于 SQLite 的 ADBC 驱动程序

其他数据源

使用 pip install "pandas[hdf5, parquet, feather, spss, excel]" 可以安装。

依赖 最低版本 pip 额外 注释
PyTables 3.8.0 hdf5 基于 HDF5 的读取 / 写入
blosc 1.21.3 hdf5 HDF5 的压缩;仅在 conda 上可用
zlib hdf5 HDF5 的压缩
fastparquet 2022.12.0 Parquet 的读取 / 写入(pyarrow 是默认的)
pyarrow 10.0.1 parquet, feather Parquet、ORC 和 feather 的读取 / 写入
pyreadstat 1.2.0 spss SPSS 文件(.sav)读取
odfpy 1.4.1 excel 读取 / 写入开放文档格式(.odf、.ods、.odt)

警告

  • 如果您想要使用 read_orc(),强烈建议使用 conda 安装 pyarrow。如果使用 pypi 安装了 pyarrow,可能会导致 read_orc() 失败,并且 read_orc() 不兼容 Windows 操作系统。

云端数据访问

使用 pip install "pandas[fss, aws, gcp]" 可以安装。

依赖 最低版本 pip 额外 注释
fsspec 2022.11.0 fss, gcp, aws 处理除了简单本地和 HTTP 之外的文件(s3fs、gcsfs 的必需依赖)
gcsfs 2022.11.0 gcp 谷歌云存储访问
pandas-gbq 0.19.0 gcp 谷歌大查询访问
s3fs 2022.11.0 aws 亚马逊 S3 访问

剪贴板

使用 pip install "pandas[clipboard]" 可以安装。

依赖 最低版本 pip 额外 注释
PyQt4/PyQt5 5.15.9 clipboard 剪贴板 I/O
qtpy 2.3.0 clipboard 剪贴板 I/O

注意

根据操作系统的不同,可能需要安装系统级包。在 Linux 上,要使剪贴板正常工作,您的系统必须安装其中一个 CLI 工具 xclipxsel

压缩

使用 pip install "pandas[compression]" 可以安装。

依赖 最低版本 pip 额外 注意
Zstandard 0.19.0 压缩 Zstandard 压缩

联盟标准

可以使用 pip install "pandas[consortium-standard]" 进行安装。

依赖 最低版本 pip 额外 注意
dataframe-api-compat 0.1.7 联盟标准 基于 pandas 的联盟标准兼容实现

性能依赖(推荐)

注:

强烈建议您安装这些库,因为它们可以提供速度改进,特别是在处理大型数据集时。

可以使用 pip install "pandas[performance]" 进行安装。

依赖 最低版本 pip 额外 注意
numexpr 2.8.4 性能 通过使用多核心以及智能分块和缓存来加速某些数值操作,从而实现大幅加速
bottleneck 1.3.6 性能 通过使用专门的 cython 程序例程来加速某些类型的 nan,从而实现大幅加速
numba 0.56.4 性能 对于接受 engine="numba" 的操作,使用将 Python 函数转换为优化的机器代码的 JIT 编译器执行引擎。

可视化

可以使用 pip install "pandas[plot, output-formatting]" 进行安装。

依赖 最低版本 pip 额外 注意
matplotlib 3.6.3 绘图 绘图库
Jinja2 3.1.2 输出格式化 使用 DataFrame.style 进行条件格式化
tabulate 0.9.0 输出格式化 以 Markdown 友好格式打印(参见 tabulate

计算

可以使用 pip install "pandas[computation]" 进行安装。

依赖 最低版本 pip 额外 注意
SciPy 1.10.0 计算 各种统计函数
xarray 2022.12.0 计算 用于 N 维数据的类似 pandas 的 API

Excel 文件

可以使用 pip install "pandas[excel]" 进行安装。

依赖 最低版本 pip 额外 注意
xlrd 2.0.1 excel 读取 Excel
xlsxwriter 3.0.5 excel 写入 Excel
openpyxl 3.1.0 excel 用于 xlsx 文件的读取/写入
pyxlsb 1.0.10 excel 读取 xlsb 文件
python-calamine 0.1.7 excel 读取 xls/xlsx/xlsb/ods 文件

HTML

可以使用 pip install "pandas[html]" 进行安装。

依赖 最低版本 pip 额外 注意
BeautifulSoup4 4.11.2 html 用于 read_html 的 HTML 解析器
html5lib 1.1 html 用于 read_html 的 HTML 解析器
lxml 4.9.2 html 用于 read_html 的 HTML 解析器

使用以下组合之一的库来使用顶层 read_html() 函数:

警告

  • 如果您安装了BeautifulSoup4,您必须安装lxml或者html5lib,或者两者都安装。只安装BeautifulSoup4 将无法使read_html()工作。

  • 非常鼓励阅读 HTML 表解析陷阱。它解释了围绕上述三个库的安装和使用的问题。

XML

可通过 pip install "pandas[xml]" 安装。

依赖项 最低版本 pip 额外 注释
lxml 4.9.2 xml read_xml 的 XML 解析器和 to_xml 的树构建器

SQL 数据库

使用 pip install "pandas[postgresql, mysql, sql-other]" 可以安装传统驱动程序。

依赖项 最低版本 pip 额外 注释
SQLAlchemy 2.0.0 postgresql, mysql, sql-other 除 SQLite 外的其他数据库的 SQL 支持
psycopg2 2.9.6 postgresql sqlalchemy 的 PostgreSQL 引擎
pymysql 1.0.2 mysql sqlalchemy 的 MySQL 引擎
adbc-driver-postgresql 0.8.0 postgresql PostgreSQL 的 ADBC 驱动程序
adbc-driver-sqlite 0.8.0 sql-other SQLite 的 ADBC 驱动程序

其他数据源

使用 pip install "pandas[hdf5, parquet, feather, spss, excel]" 可以安装。

依赖项 最低版本 pip 额外 注释
PyTables 3.8.0 hdf5 基于 HDF5 的读取/写入
blosc 1.21.3 hdf5 HDF5 的压缩;只在 conda 上可用
zlib hdf5 HDF5 的压缩
fastparquet 2022.12.0 Parquet 读取/写入(pyarrow 是默认的)
pyarrow 10.0.1 parquet, feather Parquet、ORC 和 feather 读取/写入
pyreadstat 1.2.0 spss SPSS 文件(.sav)读取
odfpy 1.4.1 excel Open document format(.odf, .ods, .odt)读取/写入

警告

  • 如果你想要使用 read_orc(),强烈建议使用 conda 安装 pyarrow。如果从 pypi 安装了 pyarrow,read_orc() 可能会失败,并且 read_orc() 不兼容 Windows 操作系统。

访问云端数据

使用pip install "pandas[fss, aws, gcp]"进行安装。

依赖 最低版本 pip 额外 备注
fsspec 2022.11.0 fss, gcp, aws 处理除简单本地和 HTTP 之外的文件(s3fs、gcsfs 的必需依赖)。
gcsfs 2022.11.0 gcp 谷歌云存储访问
pandas-gbq 0.19.0 gcp 谷歌大查询访问
s3fs 2022.11.0 aws 亚马逊 S3 访问

剪贴板

使用pip install "pandas[clipboard]"进行安装。

依赖 最低版本 pip 额外 备注
PyQt4/PyQt5 5.15.9 clipboard 剪贴板 I/O
qtpy 2.3.0 clipboard 剪贴板 I/O

注意

根据操作系统的不同,可能需要安装系统级软件包。在 Linux 上,剪贴板要操作,系统上必须安装xclipxsel中的一个 CLI 工具。

压缩

使用pip install "pandas[compression]"进行安装。

依赖 最低版本 pip 额外 备注
Zstandard 0.19.0 compression Zstandard 压缩

联盟标准

使用pip install "pandas[consortium-standard]"进行安装。

依赖 最低版本 pip 额外 备注
dataframe-api-compat 0.1.7 consortium-standard 基于 pandas 的符合联盟标准的实现

包概述

原文:pandas.pydata.org/docs/getting_started/overview.html

pandas 是一个Python包,提供快速、灵活和表达性强的数据结构,旨在使处理“关系”或“标记”数据变得简单和直观。它旨在成为在 Python 中进行实际、现实世界数据分析的基本高级构建块。此外,它还有更广泛的目标,即成为任何语言中最强大和灵活的开源数据分析/操作工具。它已经在这个目标的道路上取得了很大进展。

pandas 非常适合许多不同类型的数据:

  • 具有异构类型列的表格数据,如 SQL 表或 Excel 电子表格
  • 有序和无序(不一定是固定频率)的时间序列数据
  • 具有行和列标签的任意矩阵数据(同质或异质类型)
  • 任何其他形式的观测/统计数据集。数据不需要被标记,也可以放入 pandas 数据结构中。

pandas 的两个主要数据结构,Series(1 维)和DataFrame(2 维),处理金融、统计学、社会科学和许多工程领域的绝大多数典型用例。对于 R 用户,DataFrame提供了 R 的data.frame提供的一切,以及更多。pandas 建立在NumPy之上,旨在与许多其他第三方库在科学计算环境中很好地集成。

以下是 pandas 擅长的一些事情:

  • 处理浮点和非浮点数据中的缺失数据(表示为 NaN)非常容易
  • 大小可变性:可以从 DataFrame 和更高维对象中插入和删除
  • 自动和显式的数据对齐:对象可以显式地与一组标签对齐,或者用户可以简单地忽略标签,让SeriesDataFrame等在计算中自动为您对齐数据
  • 强大、灵活的分组功能,可以对数据集执行分割-应用-合并操作,用于聚合和转换数据
  • 使将其他 Python 和 NumPy 数据结构中的不规则、具有不同索引的数据轻松转换为 DataFrame 对象变得容易
  • 对大型数据集进行智能基于标签的切片高级索引子集操作
  • 直观的合并连接数据集
  • 灵活的数据集重塑和透视
  • 轴的分层标签(每个刻度可能有多个标签)
  • 用于从平面文件(CSV 和分隔符)、Excel 文件、数据库加载数据以及从超快速HDF5 格式保存/加载数据的强大 IO 工具
  • 时间序列特定功能:日期范围生成和频率转换,滑动窗口统计,日期移动和滞后。

这些原则中的许多都是为了解决在使用其他语言/科学研究环境时经常遇到的缺点。对于数据科学家来说,处理数据通常分为多个阶段:整理和清理数据,分析/建模,然后将分析结果组织成适合绘图或表格显示的形式。pandas 是所有这些任务的理想工具。

其他一些注意事项

  • pandas 速度快。许多底层算法部分在Cython代码中已经得到了大量调整。但是,与其他任何事物一样,一般化通常会牺牲性能。因此,如果您专注于应用程序的某一特性,您可能能够创建一个更快的专业工具。
  • pandas 是statsmodels的依赖项,使其成为 Python 统计计算生态系统中的重要部分。
  • pandas 已在金融应用程序中广泛使用。

数据结构

维度 名称 描述
1 Series 一维标记同构类型数组
2 DataFrame 通用的二维标记、可变大小的表格结构,列的类型可能异构

为什么需要多个数据结构?

最好将 pandas 数据结构视为适用于低维数据的灵活容器。例如,DataFrame 是 Series 的容器,而 Series 是标量的容器。我们希望能够以类似字典的方式向这些容器中插入和删除对象。

另外,我们希望常见 API 函数的默认行为能够考虑到时间序列和横截面数据集的典型方向。当使用 N 维数组(ndarrays)存储二维和三维数据时,用户在编写函数时需要考虑数据集的方向;轴被认为是更或多或少等效的(除非 C- 或 Fortran-连续性对性能很重要)。在 pandas 中,轴旨在为数据提供更多的语义含义;即,对于特定的数据集,很可能有一种“正确”的方式来定位数据。因此,目标是减少编写下游函数中的数据转换所需的心理努力。

例如,对于表格数据(DataFrame),更有语义的方法是考虑索引(行)和,而不是轴 0 和轴 1。因此,通过 DataFrame 的列进行迭代将产生更可读的代码:

for col in df.columns:
    series = df[col]
    # do something with series 

数据的可变性和复制

所有 pandas 数据结构都是值可变的(它们包含的值可以被改变),但不总是大小可变的。Series 的长度不能改变,但是,例如,可以在 DataFrame 中插入列。然而,绝大多数方法会产生新对象并保持输入数据不变。通常情况下,我们喜欢偏向不可变性

获取支持

pandas 问题和想法的第一站是GitHub Issue Tracker。如果您有一般问题,pandas 社区专家可以通过Stack Overflow回答。

社区

今天,pandas 得到全球志同道合的个人社区的积极支持,他们贡献了宝贵的时间和精力,帮助使开源 pandas 成为可能。感谢所有贡献者

如果您有兴趣贡献,请访问贡献指南。

pandas 是NumFOCUS赞助的项目。这将有助于确保 pandas 作为世界一流开源项目的成功,并使捐赠给该项目成为可能。

项目治理

pandas 项目自 2008 年成立以来一直在非正式使用的治理流程在项目治理文件中得到了正式化。这些文件澄清了决策的方式以及我们社区的各个元素如何互动,包括开源协作开发与可能由营利性或非营利性实体资助的工作之间的关系。

Wes McKinney 是终身仁慈独裁者(BDFL)。

开发团队

核心团队成员列表和更详细信息可在pandas 网站上找到。

机构合作伙伴

关于当前机构合作伙伴的信息可在pandas 网站页面上找到。

许可证

BSD 3-Clause License

Copyright (c) 2008-2011, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
All rights reserved.

Copyright (c) 2011-2023, Open source contributors.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

数据结构

维度 名称 描述
1 Series 1D 标记同质类型数组
2 DataFrame 通用的二维标记,大小可变的表格结构,列可能具有异构类型

为什么需要多个数据结构?

最好将 pandas 数据结构视为低维数据的灵活容器。例如,DataFrame 是 Series 的容器,而 Series 是标量的容器。我们希望能够以类似字典的方式插入和删除这些容器中的对象。

此外,我们希望常见 API 函数有合理的默认行为,考虑到时间序列和横截面数据集的典型方向。当使用 N 维数组(ndarrays)存储 2 维和 3 维数据时,用户需要考虑数据集的方向来编写函数;轴被认为是更或多或少等价的(除非 C 或 Fortran 连续性对性能有影响)。在 pandas 中,轴旨在为数据提供更多语义意义;即,对于特定数据集,可能有一种“正确”的方式来定位数据。因此,目标是减少编写下游函数中数据转换所需的心智努力量。

例如,对于表格数据(DataFrame),更有语义的方式是考虑索引(行)和,而不是轴 0 和轴 1。因此,通过 DataFrame 的列进行迭代会导致更易读的代码:

for col in df.columns:
    series = df[col]
    # do something with series 

为什么会有多个数据结构?

最好的方式是将 pandas 数据结构视为低维数据的灵活容器。例如,DataFrame 是 Series 的容器,而 Series 是标量的容器。我们希望能够以类似字典的方式向这些容器中插入和移除对象。

此外,我们希望常见 API 函数有合理的默认行为,考虑到时间序列和横截面数据集的典型方向。当使用 N 维数组(ndarrays)存储 2 维和 3 维数据时,用户需要考虑数据集的方向来编写函数;轴被认为是更或多或少等价的(除非 C 或 Fortran 连续性对性能有影响)。在 pandas 中,轴旨在为数据提供更多语义意义;即,对于特定数据集,可能有一种“正确”的方式来定位数据。因此,目标是减少编写下游函数中数据转换所需的心智努力量。

例如,对于表格数据(DataFrame),更有语义的方式是考虑索引(行)和,而不是轴 0 和轴 1。因此,通过 DataFrame 的列进行迭代会导致更易读的代码:

for col in df.columns:
    series = df[col]
    # do something with series 

可变性和数据的复制

所有的 pandas 数据结构都是值可变的(它们包含的值可以被改变),但并非总是大小可变的。Series 的长度不能被改变,但是,例如,可以在 DataFrame 中插入列。然而,绝大多数方法会产生新对象,并保持输入数据不变。一般来说,我们喜欢偏向不可变性,在合适的情况下。

获取支持

pandas 的问题和想法的第一站是GitHub Issue Tracker。如果您有一般问题,pandas 社区专家可以通过Stack Overflow回答。

社区

今天,pandas 受到全球志同道合的个人社区的积极支持,他们贡献了宝贵的时间和精力来帮助使开源 pandas 成为可能。感谢我们所有的贡献者

如果您有兴趣贡献,请访问贡献指南。

pandas 是一个NumFOCUS赞助的项目。这将有助于确保 pandas 作为一个世界一流的开源项目的成功,并使捐赠给该项目成为可能。

项目治理

pandas 项目自 2008 年成立以来一直使用的治理流程已在项目治理文件中正式规范化。这些文件澄清了如何做出决策以及我们社区各个元素之间的互动方式,包括开源协作开发与可能由营利性或非营利性实体资助的工作之间的关系。

Wes McKinney 是终身仁慈独裁者(BDFL)。

开发团队

核心团队成员列表和更详细的信息可以在pandas 网站上找到。

机构合作伙伴

当前机构合作伙伴的信息可以在pandas 网站页面上找到。

许可证

BSD 3-Clause License

Copyright (c) 2008-2011, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
All rights reserved.

Copyright (c) 2011-2023, Open source contributors.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

入门教程

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/index.html

  • pandas 处理什么类型的数据?
  • 如何读取和写入表格数据?

  • 如何选择 DataFrame 的子集?

  • 如何在 pandas 中创建图表?

  • 如何从现有列派生新列

  • 如何计算摘要统计信息

  • 如何重新设计表格布局

  • 如何合并来自多个表的数据

  • 如何轻松处理时间序列数据

  • 如何操作文本数据

pandas 处理什么类型的数据?

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/01_table_oriented.html

  • 我想开始使用 pandas

    In [1]: import pandas as pd 
    

    要加载 pandas 包并开始使用它,请导入该包。 社区约定的 pandas 别名是pd,因此假定将 pandas 加载为pd是所有 pandas 文档的标准做法。

pandas 数据表表示

../../_images/01_table_dataframe.svg

  • 我想存储泰坦尼克号的乘客数据。 对于许多乘客,我知道姓名(字符),年龄(整数)和性别(男/女)数据。

    In [2]: df = pd.DataFrame(
     ...:    {
     ...:        "Name": [
     ...:            "Braund, Mr. Owen Harris",
     ...:            "Allen, Mr. William Henry",
     ...:            "Bonnell, Miss. Elizabeth",
     ...:        ],
     ...:        "Age": [22, 35, 58],
     ...:        "Sex": ["male", "male", "female"],
     ...:    }
     ...: )
     ...: 
    
    In [3]: df
    Out[3]: 
     Name  Age     Sex
    0   Braund, Mr. Owen Harris   22    male
    1  Allen, Mr. William Henry   35    male
    2  Bonnell, Miss. Elizabeth   58  female 
    

    要手动将数据存储在表中,请创建一个DataFrame。 使用 Python 字典列表时,字典键将用作列标题,每个列表中的值将用作DataFrame的列。

一个DataFrame是一个可以在列中存储不同类型数据(包括字符、整数、浮点值、分类数据等)的二维数据结构。 它类似于电子表格、SQL 表或 R 中的data.frame

  • 表格有 3 列,每列都有一个列标签。 列标签分别是NameAgeSex

  • Name由文本数据组成,每个值都是一个字符串,列Age是数字,列Sex是文本数据。

在电子表格软件中,我们的数据的表格表示看起来会非常相似:

../../_images/01_table_spreadsheet.png

DataFrame中的每一列都是一个Series

../../_images/01_table_series.svg

  • 我只对在Age列中的数据感兴趣

    In [4]: df["Age"]
    Out[4]: 
    0    22
    1    35
    2    58
    Name: Age, dtype: int64 
    

    当选择 pandas DataFrame的单个列时,结果是一个 pandas Series。 要选择列,请在方括号[]之间使用列标签。

注意

如果您熟悉 Python dictionaries,选择单个列与基于键选择字典值非常相似。

你也可以从头开始创建一个Series

In [5]: ages = pd.Series([22, 35, 58], name="Age")

In [6]: ages
Out[6]: 
0    22
1    35
2    58
Name: Age, dtype: int64 

pandas 的Series没有列标签,因为它只是DataFrame的单列。 Series 确实有行标签。

对 DataFrame 或 Series 执行某些操作

  • 我想知道乘客的最大年龄

    我们可以通过选择Age列并应用max()DataFrame上执行此操作:

    In [7]: df["Age"].max()
    Out[7]: 58 
    

    或者到Series

    In [8]: ages.max()
    Out[8]: 58 
    

正如 max() 方法所示,您可以使用 DataFrameSeries 执行 操作。pandas 提供了许多功能,每个功能都是您可以应用于 DataFrameSeries方法。由于方法是函数,不要忘记使用括号 ()

  • 我对我的数据表的数值数据进行一些基本统计感兴趣

    In [9]: df.describe()
    Out[9]: 
     Age
    count   3.000000
    mean   38.333333
    std    18.230012
    min    22.000000
    25%    28.500000
    50%    35.000000
    75%    46.500000
    max    58.000000 
    

    describe() 方法提供了对 DataFrame 中数值数据的快速概述。由于 NameSex 列是文本数据,默认情况下不会被 describe() 方法考虑在内。

许多 pandas 操作会返回一个 DataFrame 或一个 Seriesdescribe() 方法就是一个返回 pandas Series 或 pandas DataFrame 的 pandas 操作的示例。

转至用户指南

在用户指南的关于 使用 describe 进行汇总的部分中查看更多选项

注意

这只是一个起点。与电子表格软件类似,pandas 将数据表示为具有列和行的表格。除了表示外,还有您在电子表格软件中进行的数据操作和计算,pandas 也支持。继续阅读下一篇教程,开始使用!

记住

  • 导入包,即 import pandas as pd

  • 数据表以 pandas 的 DataFrame 形式存储

  • DataFrame 中的每一列都是一个 Series

  • 您可以通过将方法应用于 DataFrameSeries 来执行操作

转至用户指南

关于 DataFrameSeries 的更详细解释在数据结构简介中提供。

pandas 数据表表示

../../_images/01_table_dataframe.svg

  • 我想存储 Titanic 的乘客数据。对于许多乘客,我知道他们的姓名(字符)、年龄(整数)和性别(男性/女性)数据。

    In [2]: df = pd.DataFrame(
     ...:    {
     ...:        "Name": [
     ...:            "Braund, Mr. Owen Harris",
     ...:            "Allen, Mr. William Henry",
     ...:            "Bonnell, Miss. Elizabeth",
     ...:        ],
     ...:        "Age": [22, 35, 58],
     ...:        "Sex": ["male", "male", "female"],
     ...:    }
     ...: )
     ...: 
    
    In [3]: df
    Out[3]: 
     Name  Age     Sex
    0   Braund, Mr. Owen Harris   22    male
    1  Allen, Mr. William Henry   35    male
    2  Bonnell, Miss. Elizabeth   58  female 
    

    要手动存储数据到表格中,创建一个 DataFrame。当使用 Python 字典的列表时,字典的键将被用作列标题,每个列表中的值将作为 DataFrame 的列。

DataFrame 是一种二维数据结构,可以在列中存储不同类型的数据(包括字符、整数、浮点值、分类数据等)。它类似于电子表格、SQL 表或 R 中的 data.frame

  • 表格有 3 列,每列都有一个列标签。列标签分别是 NameAgeSex

  • Name 包含文本数据,每个值为字符串,列 Age 是数字,列 Sex 是文本数据。

在电子表格软件中,我们的数据的表格表示看起来会非常相似:

../../_images/01_table_spreadsheet.png

每个DataFrame中的列都是一个Series

../../_images/01_table_series.svg

  • 我只对Age列中的数据感兴趣

    In [4]: df["Age"]
    Out[4]: 
    0    22
    1    35
    2    58
    Name: Age, dtype: int64 
    

    当选择 pandas DataFrame的单个列时,结果是一个 pandas Series。要选择列,请在方括号[]之间使用列标签。

注意

如果你熟悉 Python dictionaries,选择单个列与基于键选择字典值非常相似。

你也可以从头开始创建一个Series

In [5]: ages = pd.Series([22, 35, 58], name="Age")

In [6]: ages
Out[6]: 
0    22
1    35
2    58
Name: Age, dtype: int64 

一个 pandas Series没有列标签,因为它只是一个DataFrame的单列。一个 Series 有行标签。

DataFrameSeries执行一些操作

  • 我想知道乘客的最大年龄

    我们可以通过选择Age列并应用max()来对DataFrame进行操作:

    In [7]: df["Age"].max()
    Out[7]: 58 
    

    或对Series进行操作:

    In [8]: ages.max()
    Out[8]: 58 
    

正如max()方法所示,你可以对DataFrameSeries执行操作。pandas 提供了许多功能,每个功能都是可以应用于DataFrameSeries方法。由于方法是函数,请不要忘记使用括号()

  • 我对我的数据表的数值数据感兴趣的一些基本统计信息

    In [9]: df.describe()
    Out[9]: 
     Age
    count   3.000000
    mean   38.333333
    std    18.230012
    min    22.000000
    25%    28.500000
    50%    35.000000
    75%    46.500000
    max    58.000000 
    

    describe()方法提供了DataFrame中数值数据的快速概述。由于NameSex列是文本数据,默认情况下不会被describe()方法考虑在内。

许多 pandas 操作会返回一个DataFrame或一个Seriesdescribe()方法就是一个返回 pandas Series或 pandas DataFrame的 pandas 操作的示例。

转到用户指南

在用户��南的关于使用 describe 进行聚合部分查看更多关于describe的选项

注意

这只是一个起点。与电子表格软件类似,pandas 将数据表示为具有列和行的表格。除了表示,pandas 还支持电子表格软件中的数据操作和计算。继续阅读下一个教程以开始!

记住

  • 导入包,即import pandas as pd

  • 数据表以 pandas DataFrame的形式存储

  • 每个DataFrame中的列都是一个Series

  • 你可以通过将方法应用于 DataFrameSeries 来完成任务。

前往用户指南

关于 DataFrameSeries 的更详细解释可在数据结构介绍中找到。

如何读取和写入表格数据?

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/02_read_write.html

../../_images/02_io_readwrite.svg

  • 我想分析泰坦尼克号乘客数据,该数据以 CSV 文件的形式提供。

    In [2]: titanic = pd.read_csv("data/titanic.csv") 
    

    pandas 提供read_csv()函数,将存储为 csv 文件的数据读取到 pandas 的DataFrame中。pandas 支持许多不同的文件格式或数据源(csv、excel、sql、json、parquet 等),每个都带有前缀read_*

在读取数据后,务必始终检查数据。显示DataFrame时,默认会显示前后 5 行:

In [3]: titanic
Out[3]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0              1         0       3  ...   7.2500   NaN         S
1              2         1       1  ...  71.2833   C85         C
2              3         1       3  ...   7.9250   NaN         S
3              4         1       1  ...  53.1000  C123         S
4              5         0       3  ...   8.0500   NaN         S
..           ...       ...     ...  ...      ...   ...       ...
886          887         0       2  ...  13.0000   NaN         S
887          888         1       1  ...  30.0000   B42         S
888          889         0       3  ...  23.4500   NaN         S
889          890         1       1  ...  30.0000  C148         C
890          891         0       3  ...   7.7500   NaN         Q

[891 rows x 12 columns] 
  • 我想看一下 pandas DataFrame 的前 8 行。

    In [4]: titanic.head(8)
    Out[4]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    1            2         1       1  ...  71.2833   C85         C
    2            3         1       3  ...   7.9250   NaN         S
    3            4         1       1  ...  53.1000  C123         S
    4            5         0       3  ...   8.0500   NaN         S
    5            6         0       3  ...   8.4583   NaN         Q
    6            7         0       1  ...  51.8625   E46         S
    7            8         0       3  ...  21.0750   NaN         S
    
    [8 rows x 12 columns] 
    

    要查看DataFrame的前 N 行,请使用head()方法,并将所需的行数(在本例中为 8)作为参数。

注意

对最后 N 行感兴趣吗?pandas 还提供了tail()方法。例如,titanic.tail(10)将返回 DataFrame 的最后 10 行。

通过请求 pandas 的dtypes属性,可以检查 pandas 如何解释每列的数据类型:

In [5]: titanic.dtypes
Out[5]: 
PassengerId      int64
Survived         int64
Pclass           int64
Name            object
Sex             object
Age            float64
SibSp            int64
Parch            int64
Ticket          object
Fare           float64
Cabin           object
Embarked        object
dtype: object 

对于每列,列出了使用的数据类型。此DataFrame中的数据类型为整数(int64)、浮点数(float64)和字符串(object)。

注意

请求dtypes时,不使用括号!dtypesDataFrameSeries的属性。DataFrameSeries的属性不需要括号。属性表示DataFrame/Series的特征,而方法(需要括号)在第一个教程中介绍了DataFrame/Series的操作。

  • 我的同事请求将泰坦尼克号数据作为电子表格。

    In [6]: titanic.to_excel("titanic.xlsx", sheet_name="passengers", index=False) 
    

    read_*函数用于将数据读取到 pandas 中,to_*方法用于存储数据。to_excel()方法将数据存储为 excel 文件。在此示例中,sheet_name命名为passengers,而不是默认的Sheet1。通过设置index=False,行索引标签不会保存在电子表格中。

等效的读取函数read_excel()将重新加载数据到DataFrame中:

In [7]: titanic = pd.read_excel("titanic.xlsx", sheet_name="passengers") 
In [8]: titanic.head()
Out[8]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns] 
  • 我对DataFrame的技术摘要感兴趣

    In [9]: titanic.info()
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 891 entries, 0 to 890
    Data columns (total 12 columns):
     #   Column       Non-Null Count  Dtype 
    ---  ------       --------------  ----- 
     0   PassengerId  891 non-null    int64 
     1   Survived     891 non-null    int64 
     2   Pclass       891 non-null    int64 
     3   Name         891 non-null    object 
     4   Sex          891 non-null    object 
     5   Age          714 non-null    float64
     6   SibSp        891 non-null    int64 
     7   Parch        891 non-null    int64 
     8   Ticket       891 non-null    object 
     9   Fare         891 non-null    float64
     10  Cabin        204 non-null    object 
     11  Embarked     889 non-null    object 
    dtypes: float64(2), int64(5), object(5)
    memory usage: 83.7+ KB 
    

    info()方法提供有关DataFrame的技术信息,让我们更详细地解释输出:

    • 确实是一个DataFrame

    • 有 891 个条目,即 891 行。

    • 每行都有一个行标签(又称index),其值范围从 0 到 890。

    • 表格有 12 列。大多数列在每一行都有一个值(所有 891 个值都是non-null)。一些列确实有缺失值,少于 891 个non-null值。

    • NameSexCabinEmbarked由文本数据(字符串,又称object)组成。其他列是数值数据,其中一些是整数(又称integer),另一些是实数(又称float)。

    • 不同列中的数据类型(字符、整数等)通过列出dtypes进行总结。

    • 提供了用于保存 DataFrame 的大致 RAM 使用量。

记住

  • 通过read_*函数支持从许多不同文件格式或数据源将数据导入 pandas。

  • 通过不同的to_*方法提供了将数据导出到 pandas 的功能。

  • head/tail/info方法和dtypes属性对于初步检查很方便。

到用户指南

有关从 pandas 到输入和输出的完整概述,请参阅有关读取器和写入器函数的用户指南部分。

如何选择 DataFrame 的子集?

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/03_subset_data.html

如何从DataFrame中选择特定列?

../../_images/03_subset_columns.svg

  • 我对泰坦尼克号乘客的年龄感兴趣。

    In [4]: ages = titanic["Age"]
    
    In [5]: ages.head()
    Out[5]: 
    0    22.0
    1    38.0
    2    26.0
    3    35.0
    4    35.0
    Name: Age, dtype: float64 
    

    要选择单个列,请使用方括号[]与感兴趣的列名。

每个DataFrame中的列都是一个Series。当选择单个列时,返回的对象是一个 pandas Series。我们可以通过检查输出的类型来验证这一点:

In [6]: type(titanic["Age"])
Out[6]: pandas.core.series.Series 

并查看输出的shape

In [7]: titanic["Age"].shape
Out[7]: (891,) 

DataFrame.shape 是一个属性(记住读写教程中不要对属性使用括号), 用于包含行数和列数的 pandas SeriesDataFrame(nrows, ncolumns)。pandas Series 是一维的,只返回行数。

  • 我对泰坦尼克号乘客的年龄和性别感兴趣。

    In [8]: age_sex = titanic[["Age", "Sex"]]
    
    In [9]: age_sex.head()
    Out[9]: 
     Age     Sex
    0  22.0    male
    1  38.0  female
    2  26.0  female
    3  35.0  female
    4  35.0    male 
    

    要选择多个列,请在选择括号[]内使用列名列表。

注意

内部方括号定义了一个Python 列表,其中包含列名,而外部方括号用于从 pandas DataFrame 中选择数据,就像在前面的示例中看到的那样。

返回的数据类型是一个 pandas DataFrame:

In [10]: type(titanic[["Age", "Sex"]])
Out[10]: pandas.core.frame.DataFrame 
In [11]: titanic[["Age", "Sex"]].shape
Out[11]: (891, 2) 

选择返回了一个具有 891 行和 2 列的DataFrame。记住,DataFrame 是二维的,具有行和列两个维度。

转到用户指南

有关索引的基本信息,请参阅用户指南中关于索引和选择数据的部分。

如何从DataFrame中过滤特���行?

../../_images/03_subset_rows.svg

  • 我对年龄大于 35 岁的乘客感兴趣。

    In [12]: above_35 = titanic[titanic["Age"] > 35]
    
    In [13]: above_35.head()
    Out[13]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    1             2         1       1  ...  71.2833   C85         C
    6             7         0       1  ...  51.8625   E46         S
    11           12         1       1  ...  26.5500  C103         S
    13           14         0       3  ...  31.2750   NaN         S
    15           16         1       2  ...  16.0000   NaN         S
    
    [5 rows x 12 columns] 
    

    要基于条件表达式选择行,请在选择括号[]内使用条件。

选择括号内的条件titanic["Age"] > 35检查Age列的值是否大于 35 的行:

In [14]: titanic["Age"] > 35
Out[14]: 
0      False
1       True
2      False
3      False
4      False
 ... 
886    False
887    False
888    False
889    False
890    False
Name: Age, Length: 891, dtype: bool 

条件表达式的输出(>,但也可以是 ==!=<<=,...)实际上是一个具有与原始DataFrame相同行数的布尔值(TrueFalse)的 pandas Series。这样的布尔值Series可以通过将其放在选择括号[]之间来过滤DataFrame。只有值为True的行才会被选择。

我们之前知道原始泰坦尼克号DataFrame由 891 行组成。让我们通过检查结果DataFrame above_35shape属性来查看满足条件的行数:

In [15]: above_35.shape
Out[15]: (217, 12) 
  • 我对泰坦尼克号的 2 和 3 舱位乘客感兴趣。

    In [16]: class_23 = titanic[titanic["Pclass"].isin([2, 3])]
    
    In [17]: class_23.head()
    Out[17]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    2            3         1       3  ...   7.9250   NaN         S
    4            5         0       3  ...   8.0500   NaN         S
    5            6         0       3  ...   8.4583   NaN         Q
    7            8         0       3  ...  21.0750   NaN         S
    
    [5 rows x 12 columns] 
    

    与条件表达式类似,isin() 条件函数会对提供的列表中的每一行返回True。要基于这样的函数过滤行,请在选择括号[]内使用条件函数。在这种情况下,选择括号内的条件titanic["Pclass"].isin([2, 3])检查Pclass列为 2 或 3 的行。

上述操作等同于按照舱位为 2 或 3 的行进行筛选,并使用|(或)运算符将两个语句组合在一起:

In [18]: class_23 = titanic[(titanic["Pclass"] == 2) | (titanic["Pclass"] == 3)]

In [19]: class_23.head()
Out[19]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
2            3         1       3  ...   7.9250   NaN         S
4            5         0       3  ...   8.0500   NaN         S
5            6         0       3  ...   8.4583   NaN         Q
7            8         0       3  ...  21.0750   NaN         S

[5 rows x 12 columns] 

注意

在组合多个条件语句时,每个条件必须用括号()括起来。此外,不能使用or/and,而是需要使用or运算符|and运算符&

到用户指南

请查看用户指南中关于布尔索引或 isin 函数的专门部分。

  • 我想处理已知年龄的乘客数据。

    In [20]: age_no_na = titanic[titanic["Age"].notna()]
    
    In [21]: age_no_na.head()
    Out[21]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    1            2         1       1  ...  71.2833   C85         C
    2            3         1       3  ...   7.9250   NaN         S
    3            4         1       1  ...  53.1000  C123         S
    4            5         0       3  ...   8.0500   NaN         S
    
    [5 rows x 12 columns] 
    

    notna() 条件函数会对值不是Null值的每一行返回True。因此,可以将其与选择括号[]结合使用来过滤数据表。

你可能会想知道实际发生了什么变化,因为前 5 行仍然是相同的值。验证的一种方法是检查形状是否发生了变化:

In [22]: age_no_na.shape
Out[22]: (714, 12) 

到用户指南

有关缺失值的更多专用函数,请参阅用户指南中关于处理缺失数据的部分。

如何从DataFrame中选择特定的行和列?

../../_images/03_subset_columns_rows.svg

  • 我对 35 岁以上的乘客姓名感兴趣。

    In [23]: adult_names = titanic.loc[titanic["Age"] > 35, "Name"]
    
    In [24]: adult_names.head()
    Out[24]: 
    1     Cumings, Mrs. John Bradley (Florence Briggs Th...
    6                               McCarthy, Mr. Timothy J
    11                             Bonnell, Miss. Elizabeth
    13                          Andersson, Mr. Anders Johan
    15                     Hewlett, Mrs. (Mary D Kingcome) 
    Name: Name, dtype: object 
    

    在这种情况下,一次性对行和列进行子集操作,仅使用选择括号[]已经不够了。在选择括号[]前面需要使用loc/iloc运算符。使用loc/iloc时,逗号前面的部分是你想要的行,逗号后面的部分是你想要选择的列。

当使用列名、行标签或条件表达式时,请在选择括号[]前面使用loc运算符。对于逗号前后的部分,可以使用单个标签、标签列表、标签切片、条件表达式或冒号。使用冒号指定你想选择所有行或列。

  • 我对第 10 到 25 行和第 3 到 5 列感兴趣。

    In [25]: titanic.iloc[9:25, 2:5]
    Out[25]: 
     Pclass                                 Name     Sex
    9        2  Nasser, Mrs. Nicholas (Adele Achem)  female
    10       3      Sandstrom, Miss. Marguerite Rut  female
    11       1             Bonnell, Miss. Elizabeth  female
    12       3       Saundercock, Mr. William Henry    male
    13       3          Andersson, Mr. Anders Johan    male
    ..     ...                                  ...     ...
    20       2                 Fynney, Mr. Joseph J    male
    21       2                Beesley, Mr. Lawrence    male
    22       3          McGowan, Miss. Anna "Annie"  female
    23       1         Sloper, Mr. William Thompson    male
    24       3        Palsson, Miss. Torborg Danira  female
    
    [16 rows x 3 columns] 
    

    再次,一次性对行和列的子集进行选择,仅使用选择括号[]已经不再足够。当特别关注表中位置的某些行和/或列时,请在选择括号[]前使用iloc运算符。

使用lociloc选择特定行和/或列时,可以为所选数据分配新值。例如,为第四列的前 3 个元素分配名称anonymous

In [26]: titanic.iloc[0:3, 3] = "anonymous"

In [27]: titanic.head()
Out[27]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns] 

转到用户指南

查看用户指南关于索引选择的不同选择部分,以更深入了解lociloc的用法。

记住

  • 在选择数据子集时,使用方括号[]

  • 在这些括号内,您可以使用单个列/行标签、列/行标签列表、标签切片、条件表达式或冒号。

  • 使用loc选择特定行和/或列时,请使用行和列名称。

  • 使用iloc选择特定行和/或列时,请使用表中的位置。

  • 您可以基于loc/iloc分配新值给选择。

转到用户指南

用户指南页面提供了有关索引和选择数据的完整概述。

如何从DataFrame中选择特定列?

../../_images/03_subset_columns.svg

  • 我对泰坦尼克号乘客的年龄感兴趣。

    In [4]: ages = titanic["Age"]
    
    In [5]: ages.head()
    Out[5]: 
    0    22.0
    1    38.0
    2    26.0
    3    35.0
    4    35.0
    Name: Age, dtype: float64 
    

    要选择单列,使用方括号[]和感兴趣的列的列名。

DataFrame中的每一列都是一个Series。当选择单列时,返回的对象是一个 pandas Series。我们可以通过检查输出的类型来验证这一点:

In [6]: type(titanic["Age"])
Out[6]: pandas.core.series.Series 

并查看输出的shape

In [7]: titanic["Age"].shape
Out[7]: (891,) 

DataFrame.shape是一个属性(请记住读写教程,对于属性不要使用括号),包含行数和列数:(nrows, ncolumns)。pandas Series 是 1 维的,只返回行数。

  • 我对泰坦尼克号乘客的年龄和性别感兴趣。

    In [8]: age_sex = titanic[["Age", "Sex"]]
    
    In [9]: age_sex.head()
    Out[9]: 
     Age     Sex
    0  22.0    male
    1  38.0  female
    2  26.0  female
    3  35.0  female
    4  35.0    male 
    

    要选择多列,使用选择括号[]内的列名列表。

注意

内部方括号定义了一个Python 列表,其中包含列名,而外部方括号用于从 pandas DataFrame中选择数据,就像在前面的示例中看到的那样。

返回的数据类型是一个 pandas DataFrame:

In [10]: type(titanic[["Age", "Sex"]])
Out[10]: pandas.core.frame.DataFrame 
In [11]: titanic[["Age", "Sex"]].shape
Out[11]: (891, 2) 

选择返回了一个具有 891 行和 2 列的DataFrame。请记住,DataFrame是二维的,具有行和列两个维度。

转到用户指南

有关索引的基本信息,请参阅用户指南中关于索引和选择数据的部分。

如何从DataFrame中筛选特定行?

../../_images/03_subset_rows.svg

  • 我对 35 岁以上的乘客感兴趣。

    In [12]: above_35 = titanic[titanic["Age"] > 35]
    
    In [13]: above_35.head()
    Out[13]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    1             2         1       1  ...  71.2833   C85         C
    6             7         0       1  ...  51.8625   E46         S
    11           12         1       1  ...  26.5500  C103         S
    13           14         0       3  ...  31.2750   NaN         S
    15           16         1       2  ...  16.0000   NaN         S
    
    [5 rows x 12 columns] 
    

    要基于条件表达式选择行,请在选择括号[]内使用条件。

选择括号内条件titanic["Age"] > 35检查Age列数值大于 35 的行:

In [14]: titanic["Age"] > 35
Out[14]: 
0      False
1       True
2      False
3      False
4      False
 ... 
886    False
887    False
888    False
889    False
890    False
Name: Age, Length: 891, dtype: bool 

条件表达式的输出(>, 也可以是 ==, !=, <, <=,…)实际上是一个布尔值的 pandas SeriesTrueFalse)与原始 DataFrame 行数相同。这样的布尔值 Series 可以用于通过将其放在选择括号[]之间来过滤 DataFrame。只有值为True的行将被选中。

我们之前知道原始泰坦尼克DataFrame由 891 行组成。让我们通过检查above_35的结果DataFrameshape属性来查看满足条件的行数:

In [15]: above_35.shape
Out[15]: (217, 12) 
  • 我对泰坦尼克号 2 和 3 舱位的乘客感兴趣。

    In [16]: class_23 = titanic[titanic["Pclass"].isin([2, 3])]
    
    In [17]: class_23.head()
    Out[17]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    2            3         1       3  ...   7.9250   NaN         S
    4            5         0       3  ...   8.0500   NaN         S
    5            6         0       3  ...   8.4583   NaN         Q
    7            8         0       3  ...  21.0750   NaN         S
    
    [5 rows x 12 columns] 
    

    与条件表达式类似,isin()条件函数对于每一行数值在提供的列表中时返回True。要基于此类函数过滤行,请在选择括号[]内使用条件函数。在这种情况下,选择括号内条件titanic["Pclass"].isin([2, 3])检查Pclass列数值为 2 或 3 的行。

上述等同于按照舱位为 2 或 3 的行进行过滤,并使用|(或)运算符将两个语句组合:

In [18]: class_23 = titanic[(titanic["Pclass"] == 2) | (titanic["Pclass"] == 3)]

In [19]: class_23.head()
Out[19]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
2            3         1       3  ...   7.9250   NaN         S
4            5         0       3  ...   8.0500   NaN         S
5            6         0       3  ...   8.4583   NaN         Q
7            8         0       3  ...  21.0750   NaN         S

[5 rows x 12 columns] 

注意

当组合多个条件语句时,每个条件必须用括号()括起来。此外,不能使用 or/and,而是需要使用 or 运算符 |and 运算符 &

转到用户指南

请查看用户指南中关于布尔索引或 isin 函数的专门部分。

  • 我想处理已知年龄的乘客数据。

    In [20]: age_no_na = titanic[titanic["Age"].notna()]
    
    In [21]: age_no_na.head()
    Out[21]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    1            2         1       1  ...  71.2833   C85         C
    2            3         1       3  ...   7.9250   NaN         S
    3            4         1       1  ...  53.1000  C123         S
    4            5         0       3  ...   8.0500   NaN         S
    
    [5 rows x 12 columns] 
    

    notna()条件函数对于每一行数值不是Null值时返回True。因此,可以与选择括号[]结合使用来过滤数据表。

你可能想知道实际发生了什么变化,因为前 5 行仍然是相同的值。验证的一种方法是检查形状是否发生了变化:

In [22]: age_no_na.shape
Out[22]: (714, 12) 

转到用户指南

想要了解更多关于处理缺失值的专用功能,请查看用户指南中关于处理缺失数据的部分。

如何从DataFrame中选择特定的行和列?

../../_images/03_subset_columns_rows.svg

  • 我对年龄大于 35 岁的乘客的姓名感兴趣。

    In [23]: adult_names = titanic.loc[titanic["Age"] > 35, "Name"]
    
    In [24]: adult_names.head()
    Out[24]: 
    1     Cumings, Mrs. John Bradley (Florence Briggs Th...
    6                               McCarthy, Mr. Timothy J
    11                             Bonnell, Miss. Elizabeth
    13                          Andersson, Mr. Anders Johan
    15                     Hewlett, Mrs. (Mary D Kingcome) 
    Name: Name, dtype: object 
    

    在这种情况下,一次性选择行和列的子集,并且仅使用选择括号[]已经不再足够。需要在选择括号[]前使用loc/iloc运算符。在使用loc/iloc时,逗号前面的部分是您想要的行,逗号后面的部分是您要选择的列。

当使用列名称、行标签或条件表达式时,请在选择括号[]前使用loc运算符。对于逗号前后的部分,您可以使用单个标签、标签列表、标签切片、条件表达式或冒号。使用冒号指定您要选择所有行或列。

  • 我对第 10 到 25 行和第 3 到 5 列感兴趣。

    In [25]: titanic.iloc[9:25, 2:5]
    Out[25]: 
     Pclass                                 Name     Sex
    9        2  Nasser, Mrs. Nicholas (Adele Achem)  female
    10       3      Sandstrom, Miss. Marguerite Rut  female
    11       1             Bonnell, Miss. Elizabeth  female
    12       3       Saundercock, Mr. William Henry    male
    13       3          Andersson, Mr. Anders Johan    male
    ..     ...                                  ...     ...
    20       2                 Fynney, Mr. Joseph J    male
    21       2                Beesley, Mr. Lawrence    male
    22       3          McGowan, Miss. Anna "Annie"  female
    23       1         Sloper, Mr. William Thompson    male
    24       3        Palsson, Miss. Torborg Danira  female
    
    [16 rows x 3 columns] 
    

    再次,一次性选择行和列的子集,并且仅使用选择括号[]已经不再足够。当特别关注表中位置的某些行和/或列时,请在选择括号[]前使用iloc运算符。

在使用lociloc选择特定行和/或列时,可以为所选数据分配新值。例如,要将名称anonymous分配给第四列的前 3 个元素:

In [26]: titanic.iloc[0:3, 3] = "anonymous"

In [27]: titanic.head()
Out[27]: 
 PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns] 

前往用户指南

查看用户指南中关于索引的不同选择以获取有关lociloc用法的更多见解。

记住

  • 在选择数据子集时,使用方括号[]

  • 在这些括号内,您可以使用单个列/行标签、列/行标签列表、标签切片、条件表达式或冒号。

  • 使用loc选择特定行和/或列时,请使用行和列名称。

  • 使用iloc选择特定行和/或列时,请使用表中的位置。

  • 您可以根据loc/iloc的选择分配新值。

前往用户指南

用户指南页面提供了有关索引和选择数据的完整概述。

如何在 pandas 中创建图表?

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/04_plotting.html

../../_images/04_plot_overview.svg

In [1]: import pandas as pd

In [2]: import matplotlib.pyplot as plt 

本教程使用的数据:

  • 空气质量数据

    本教程使用关于(NO_2)的空气质量数据,由OpenAQ提供,并使用py-openaq包。air_quality_no2.csv数据集提供了分别来自巴黎、安特卫普和伦敦的测量站FR04014BETR801London Westminster的(NO_2)值。

    原始数据

    In [3]: air_quality = pd.read_csv("data/air_quality_no2.csv", index_col=0, parse_dates=True)
    
    In [4]: air_quality.head()
    Out[4]: 
     station_antwerp  station_paris  station_london
    datetime 
    2019-05-07 02:00:00              NaN            NaN            23.0
    2019-05-07 03:00:00             50.5           25.0            19.0
    2019-05-07 04:00:00             45.0           27.7            19.0
    2019-05-07 05:00:00              NaN           50.4            16.0
    2019-05-07 06:00:00              NaN           61.9             NaN 
    

    注意

    使用read_csv函数的index_colparse_dates参数,将第一(0)列定义为生成的DataFrame的索引,并将列中的日期转换为Timestamp对象。

  • 我想快速地对数据进行可视化检查。

    In [5]: air_quality.plot()
    Out[5]: <Axes: xlabel='datetime'>
    
    In [6]: plt.show() 
    

    ../../_images/04_airqual_quick.png

    使用DataFrame,pandas 默认为具有数值数据的每列创建一条线图。

  • 我只想绘制数据表中来自巴黎的列。

    In [7]: air_quality["station_paris"].plot()
    Out[7]: <Axes: xlabel='datetime'>
    
    In [8]: plt.show() 
    

    ../../_images/04_airqual_paris.png

    要绘制特定列,请结合子集数据教程中的选择方法和plot()方法。因此,plot()方法适用于SeriesDataFrame

  • 我想要直观比较伦敦和巴黎测得的(NO_2)值。

    In [9]: air_quality.plot.scatter(x="station_london", y="station_paris", alpha=0.5)
    Out[9]: <Axes: xlabel='station_london', ylabel='station_paris'>
    
    In [10]: plt.show() 
    

    ../../_images/04_airqual_scatter.png

在使用plot函数时,除了默认的line图之外,还有许多可用于绘制数据的替代方法。让我们使用一些标准 Python 来了解可用绘图方法:

In [11]: [
 ....:    method_name
 ....:    for method_name in dir(air_quality.plot)
 ....:    if not method_name.startswith("_")
 ....: ]
 ....: 
Out[11]: 
['area',
 'bar',
 'barh',
 'box',
 'density',
 'hexbin',
 'hist',
 'kde',
 'line',
 'pie',
 'scatter'] 

注意

在许多开发环境以及 IPython 和 Jupyter Notebook 中,使用 TAB 键可以获得可用方法的概览,例如 air_quality.plot. + TAB。

其中一个选项是DataFrame.plot.box(),它指的是箱线图box方法适用于空气质量示例数据:

In [12]: air_quality.plot.box()
Out[12]: <Axes: >

In [13]: plt.show() 

../../_images/04_airqual_boxplot.png用户指南

除了默认的折线图之外,有关支持的绘图样式的介绍,请参阅用户指南中关于支持的绘图样式的部分。

  • 我想将每列分别放在单独的子图中。

    In [14]: axs = air_quality.plot.area(figsize=(12, 4), subplots=True)
    
    In [15]: plt.show() 
    

    ../../_images/04_airqual_area_subplot.png

    通过plot函数的subplots参数支持为每个数据列创建单独的子图。值得回顾每个 pandas 绘图函数中提供的内置选项。

到用户指南

更多格式选项在用户指南的绘图格式化部分有详细说明。

  • 我想进一步自定义、扩展或保存生成的图。

    In [16]: fig, axs = plt.subplots(figsize=(12, 4))
    
    In [17]: air_quality.plot.area(ax=axs)
    Out[17]: <Axes: xlabel='datetime'>
    
    In [18]: axs.set_ylabel("NO$_2$ concentration")
    Out[18]: Text(0, 0.5, 'NO$_2$ concentration')
    
    In [19]: fig.savefig("no2_concentrations.png")
    
    In [20]: plt.show() 
    

    ../../_images/04_airqual_customized.png

pandas 创建的每个绘图对象都是一个Matplotlib对象。由于 Matplotlib 提供了大量自定义绘图的选项,使 pandas 和 Matplotlib 之间的链接明确,可以将 Matplotlib 的所有功能应用于绘图。这种策略在前面的示例中应用:

fig, axs = plt.subplots(figsize=(12, 4))        # Create an empty Matplotlib Figure and Axes
air_quality.plot.area(ax=axs)                   # Use pandas to put the area plot on the prepared Figure/Axes
axs.set_ylabel("NO$_2$ concentration")          # Do any Matplotlib customization you like
fig.savefig("no2_concentrations.png")           # Save the Figure/Axes using the existing Matplotlib method.
plt.show()                                      # Display the plot 

记住

  • .plot.*方法适用于 Series 和 DataFrames。

  • 默认情况下,每列都被绘制为不同的元素(线条、箱线图等)。

  • 由 pandas 创建的任何绘图都是一个 Matplotlib 对象。

到用户指南

在可视化页面中提供了 pandas 绘图的完整概述。

如何从现有列派生新列

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/05_add_columns.html

../../_images/05_newcolumn_1.svg

  • 我想要以 mg/m(³)表示伦敦站的(NO_2)浓度。

    (如果我们假设温度为 25 摄氏度,压力为 1013 百帕,转换系数为 1.882)

    In [4]: air_quality["london_mg_per_cubic"] = air_quality["station_london"] * 1.882
    
    In [5]: air_quality.head()
    Out[5]: 
     station_antwerp  ...  london_mg_per_cubic
    datetime                              ... 
    2019-05-07 02:00:00              NaN  ...               43.286
    2019-05-07 03:00:00             50.5  ...               35.758
    2019-05-07 04:00:00             45.0  ...               35.758
    2019-05-07 05:00:00              NaN  ...               30.112
    2019-05-07 06:00:00              NaN  ...                  NaN
    
    [5 rows x 4 columns] 
    

    要创建新列,请使用[]括号,新列名称位于赋值的左侧。

注意

值的计算是逐元素进行的。这意味着给定列中的所有值一次性乘以值 1.882。您不需要使用循环迭代每一行!

../../_images/05_newcolumn_2.svg

  • 我想检查巴黎与安特卫普的比值,并将结果保存在一个新列中。

    In [6]: air_quality["ratio_paris_antwerp"] = (
     ...:    air_quality["station_paris"] / air_quality["station_antwerp"]
     ...: )
     ...: 
    
    In [7]: air_quality.head()
    Out[7]: 
     station_antwerp  ...  ratio_paris_antwerp
    datetime                              ... 
    2019-05-07 02:00:00              NaN  ...                  NaN
    2019-05-07 03:00:00             50.5  ...             0.495050
    2019-05-07 04:00:00             45.0  ...             0.615556
    2019-05-07 05:00:00              NaN  ...                  NaN
    2019-05-07 06:00:00              NaN  ...                  NaN
    
    [5 rows x 5 columns] 
    

    计算再次逐元素进行,因此/适用于每行的值

还有其他数学运算符(+-*/,…)或逻辑运算符(<>==,…)逐元素工作。后者在子集数据教程中已经用于使用条件表达式过滤表的行。

如果您需要更高级的逻辑,可以通过apply()使用任意 Python 代码。

  • 我想将数据列重命名为由OpenAQ使用的相应站点标识符。

    In [8]: air_quality_renamed = air_quality.rename(
     ...:    columns={
     ...:        "station_antwerp": "BETR801",
     ...:        "station_paris": "FR04014",
     ...:        "station_london": "London Westminster",
     ...:    }
     ...: )
     ...: 
    
    In [9]: air_quality_renamed.head()
    Out[9]: 
     BETR801  FR04014  ...  london_mg_per_cubic  ratio_paris_antwerp
    datetime                               ... 
    2019-05-07 02:00:00      NaN      NaN  ...               43.286                  NaN
    2019-05-07 03:00:00     50.5     25.0  ...               35.758             0.495050
    2019-05-07 04:00:00     45.0     27.7  ...               35.758             0.615556
    2019-05-07 05:00:00      NaN     50.4  ...               30.112                  NaN
    2019-05-07 06:00:00      NaN     61.9  ...                  NaN                  NaN
    
    [5 rows x 5 columns] 
    

    rename()函数可用于行标签和列标签。提供一个字典,键是当前名称,值是要更新的新名称以更新相应的名称。

映射不应仅限于固定名称,还可以是映射函数。例如,也可以使用函数将列名称转换为小写字母:

In [10]: air_quality_renamed = air_quality_renamed.rename(columns=str.lower)

In [11]: air_quality_renamed.head()
Out[11]: 
 betr801  fr04014  ...  london_mg_per_cubic  ratio_paris_antwerp
datetime                               ... 
2019-05-07 02:00:00      NaN      NaN  ...               43.286                  NaN
2019-05-07 03:00:00     50.5     25.0  ...               35.758             0.495050
2019-05-07 04:00:00     45.0     27.7  ...               35.758             0.615556
2019-05-07 05:00:00      NaN     50.4  ...               30.112                  NaN
2019-05-07 06:00:00      NaN     61.9  ...                  NaN                  NaN

[5 rows x 5 columns] 

到用户指南

有关列或行标签重命名的详细信息,请参阅用户指南中的重命名标签部分。

记住

  • 通过在[]之间的新列名称处将输出分配给 DataFrame 来创建新列。

  • 运算是逐元素进行的,不需要循环遍历行。

  • 使用字典或函数与rename一起重命名行标签或列名称。

到用户指南

用户指南中有一个独立的部分介绍了列的添加和删除。

如何计算摘要统计信息

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/06_calculate_statistics.html

聚合统计

../../_images/06_aggregate.svg

  • 泰坦尼克号乘客的平均年龄是多少?

    In [4]: titanic["Age"].mean()
    Out[4]: 29.69911764705882 
    

可用不同统计数据并可以应用于具有数值数据的列。一般情况下,操作将排除缺失数据,并默认跨行操作。

../../_images/06_reduction.svg

  • 泰坦尼克号乘客的中位年龄和票价是多少?

    In [5]: titanic[["Age", "Fare"]].median()
    Out[5]: 
    Age     28.0000
    Fare    14.4542
    dtype: float64 
    

    对于DataFrame的多列(选择两列返回一个DataFrame,参见子集数据教程)应用的统计数据针对每个数字列进行计算。

聚合统计信息可以同时计算多列。记得从第一个教程中的describe函数吗?

In [6]: titanic[["Age", "Fare"]].describe()
Out[6]: 
 Age        Fare
count  714.000000  891.000000
mean    29.699118   32.204208
std     14.526497   49.693429
min      0.420000    0.000000
25%     20.125000    7.910400
50%     28.000000   14.454200
75%     38.000000   31.000000
max     80.000000  512.329200 

与预定义的统计数据不同,可以使用DataFrame.agg()方法定义给定列的特定组合的聚合统计信息:

In [7]: titanic.agg(
 ...:    {
 ...:        "Age": ["min", "max", "median", "skew"],
 ...:        "Fare": ["min", "max", "median", "mean"],
 ...:    }
 ...: )
 ...: 
Out[7]: 
 Age        Fare
min      0.420000    0.000000
max     80.000000  512.329200
median  28.000000   14.454200
skew     0.389108         NaN
mean          NaN   32.204208 

到用户指南

在用户指南中提供了关于描述性统计的详细信息,参见描述性统计一节。

按类别分组的聚合统计

../../_images/06_groupby.svg

  • 泰坦尼克号乘客的男性与女性的平均年龄是多少?

    In [8]: titanic[["Sex", "Age"]].groupby("Sex").mean()
    Out[8]: 
     Age
    Sex 
    female  27.915709
    male    30.726645 
    

    由于我们的兴趣是每个性别的平均年龄,首先对这两列进行子选择:titanic[["Sex", "Age"]]。然后,在Sex列上应用groupby()方法,以每个类别生成一个分组。计算并返回每个性别的平均年龄。

计算给定统计数据(例如mean年龄)对于列中的每个类别(例如Sex列中的男性/女性)是一种常见模式。groupby方法用于支持这种类型的操作。这适用于更通用的split-apply-combine模式:

  • 拆分数据成组

  • 对每个组独立应用一个函数

  • 合并结果到一个数据结构中

在 pandas 中,应用和合并步骤通常一起完成。

在前面的示例中,我们明确选择了前两列。如果没有,将通过传递numeric_only=Truemean方法应用于包含数字列的每一列:

In [9]: titanic.groupby("Sex").mean(numeric_only=True)
Out[9]: 
 PassengerId  Survived    Pclass  ...     SibSp     Parch       Fare
Sex                                      ... 
female   431.028662  0.742038  2.159236  ...  0.694268  0.649682  44.479818
male     454.147314  0.188908  2.389948  ...  0.429809  0.235702  25.523893

[2 rows x 7 columns] 

获取Pclass的平均值并没有太多意义。如果我们只对每个性别的平均年龄感兴趣,那么在分组数据上也支持对列的选择(如通常所见的方括号[]):

In [10]: titanic.groupby("Sex")["Age"].mean()
Out[10]: 
Sex
female    27.915709
male      30.726645
Name: Age, dtype: float64 

../../_images/06_groupby_select_detail.svg

注意

Pclass 列包含数字数据,但实际上代表着 3 个类别(或因子),分别标有 '1'、'2' 和 '3' 的标签。对这些数据进行统计计算并不太合理。因此,pandas 提供了 Categorical 数据类型来处理这种类型的数据。更多信息请参阅用户指南中的分类数据部分。

  • 在性别和舱位等级组合中,票价的平均值是多少?

    In [11]: titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
    Out[11]: 
    Sex     Pclass
    female  1         106.125798
     2          21.970121
     3          16.118810
    male    1          67.226127
     2          19.741782
     3          12.661633
    Name: Fare, dtype: float64 
    

    可以同时通过多列进行分组。将列名作为列表提供给 groupby() 方法。

转至用户指南

关于分组-应用-合并方法的全面描述可在用户指南的分组操作部分找到。

按类别计算记录数

../../_images/06_valuecounts.svg

  • 在每个舱位等级中的乘客数量是多少?

    In [12]: titanic["Pclass"].value_counts()
    Out[12]: 
    Pclass
    3    491
    1    216
    2    184
    Name: count, dtype: int64 
    

    value_counts() 方法计算列中每个类别的记录数。

该函数是一个快捷方式,因为实际上是一个组合了分组操作和对每个组内记录数进行计数的操作:

In [13]: titanic.groupby("Pclass")["Pclass"].count()
Out[13]: 
Pclass
1    216
2    184
3    491
Name: Pclass, dtype: int64 

注意

sizecount 都可以与 groupby 结合使用。而 size 包括 NaN 值并且仅提供行数(表的大小),count 则排除缺失值。在 value_counts 方法中,使用 dropna 参数来包含或排除 NaN 值。

转至用户指南

用户指南有一个专门介绍 value_counts 的部分,请参阅离散化页面。

记住

  • 聚合统计可以在整个列或行上计算。

  • groupby 提供了 分组-应用-合并 模式的强大功能。

  • value_counts 是一个方便的快捷方式,用于计算变量的每个类别中的条目数。

转至用户指南

关于分组-应用-合并方法的全面描述可在用户指南的分组操作页面找到。

聚合统计

../../_images/06_aggregate.svg

  • 泰坦尼克号乘客的平均年龄是多少?

    In [4]: titanic["Age"].mean()
    Out[4]: 29.69911764705882 
    

不同的统计数据可用,并且可以应用于具有数字数据的列。操作通常会排除缺失数据,并默认跨行操作。

../../_images/06_reduction.svg

  • 泰坦尼克号乘客的中位年龄和票价是多少?

    In [5]: titanic[["Age", "Fare"]].median()
    Out[5]: 
    Age     28.0000
    Fare    14.4542
    dtype: float64 
    

    DataFrame的多列(选择两列返回一个DataFrame,参见子集数据教程)应用的统计量是针对每个数值列进行计算的。

聚合统计可以同时针对多列进行计算。还记得第一个教程中的describe函数吗?

In [6]: titanic[["Age", "Fare"]].describe()
Out[6]: 
 Age        Fare
count  714.000000  891.000000
mean    29.699118   32.204208
std     14.526497   49.693429
min      0.420000    0.000000
25%     20.125000    7.910400
50%     28.000000   14.454200
75%     38.000000   31.000000
max     80.000000  512.329200 

可以使用DataFrame.agg()方法定义给定列的特定聚合统计量组合,而不是预定义的统计量:

In [7]: titanic.agg(
 ...:    {
 ...:        "Age": ["min", "max", "median", "skew"],
 ...:        "Fare": ["min", "max", "median", "mean"],
 ...:    }
 ...: )
 ...: 
Out[7]: 
 Age        Fare
min      0.420000    0.000000
max     80.000000  512.329200
median  28.000000   14.454200
skew     0.389108         NaN
mean          NaN   32.204208 

转到用户指南

关于描述性统计的详细信息,请参阅用户指南中的描述性统计部分。

按类别分组的聚合统计

../../_images/06_groupby.svg

  • 泰坦尼克号男性与女性乘客的平均年龄分别是多少?

    In [8]: titanic[["Sex", "Age"]].groupby("Sex").mean()
    Out[8]: 
     Age
    Sex 
    female  27.915709
    male    30.726645 
    

    由于我们感兴趣的是每个性别的平均年龄,首先对这两列进行了子选择:titanic[["Sex", "Age"]]。然后,应用groupby()方法在Sex列上进行分组,以每个类别创建一个组。计算并返回每个性别的平均年龄。

对于某一列中的每个类别(例如Sex列中的男性/女性)计算给定统计量(例如mean年龄)是一种常见模式。groupby方法用于支持此类操作。这符合更一般的split-apply-combine模式:

  • 将数据分割成组

  • 对每个分组独立应用一个函数

  • 将结果合并成数据结构

在 pandas 中,应用和合并步骤通常一起完成。

在前面的示例中,我们首先明确选择了 2 列。如果没有,则通过传递numeric_only=Truemean方法应用于包含数值列的每列:

In [9]: titanic.groupby("Sex").mean(numeric_only=True)
Out[9]: 
 PassengerId  Survived    Pclass  ...     SibSp     Parch       Fare
Sex                                      ... 
female   431.028662  0.742038  2.159236  ...  0.694268  0.649682  44.479818
male     454.147314  0.188908  2.389948  ...  0.429809  0.235702  25.523893

[2 rows x 7 columns] 

获取Pclass的平均值并没有太多意义。如果我们只对每个性别的平均年龄感兴趣,那么在分组数据上也支持对列(如常规的方括号[])进行选择:

In [10]: titanic.groupby("Sex")["Age"].mean()
Out[10]: 
Sex
female    27.915709
male      30.726645
Name: Age, dtype: float64 

../../_images/06_groupby_select_detail.svg

注意

Pclass列包含数值数据,但实际上表示 3 个类别(或因子),分别具有标签‘1’、‘2’和‘3’。对这些进行统计没有太多意义。因此,pandas 提供了Categorical数据类型来处理这种类型的数据。更多信息请参阅用户指南中的分类数据部分。

  • 每个性别和舱位等级组合的平均票价是多少?

    In [11]: titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
    Out[11]: 
    Sex     Pclass
    female  1         106.125798
     2          21.970121
     3          16.118810
    male    1          67.226127
     2          19.741782
     3          12.661633
    Name: Fare, dtype: float64 
    

    分组可以同时按多个列进行。将列名作为列表提供给 groupby() 方法。

用户指南

关于分组操作的分割-应用-组合方法的完整描述,请参阅用户指南中的分组操作部分。

按类别计算记录数

../../_images/06_valuecounts.svg

  • 每个客舱等级的乘客数量是多少?

    In [12]: titanic["Pclass"].value_counts()
    Out[12]: 
    Pclass
    3    491
    1    216
    2    184
    Name: count, dtype: int64 
    

    value_counts() 方法计算列中每个类别的记录数。

该函数是一个快捷方式,实际上是一个组合操作,结合了每个组内记录数的分组操作:

In [13]: titanic.groupby("Pclass")["Pclass"].count()
Out[13]: 
Pclass
1    216
2    184
3    491
Name: Pclass, dtype: int64 

注意

sizecount 都可以与 groupby 结合使用。而 size 包括 NaN 值并且仅提供行数(表的大小),count 排除缺失值。在 value_counts 方法中,使用 dropna 参数来包含或排除 NaN 值。

用户指南

用户指南有一个专门介绍value_counts的部分,请参阅离散化页面。

记住

  • 可以在整个列或行上计算聚合统计信息。

  • groupby 提供了分割-应用-组合模式的强大功能。

  • value_counts 是计算变量每个类别中条目数量的便捷快捷方式。

用户指南

关于分组操作的用户指南页面中提供了关于分割-应用-组合方法的完整描述。

如何重新排列表格布局

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/07_reshape_table_layout.html

排序表格行

  • 我想根据乘客的年龄对泰坦尼克号数据进行排序。

    In [6]: titanic.sort_values(by="Age").head()
    Out[6]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    803          804         1       3  ...   8.5167   NaN         C
    755          756         1       2  ...  14.5000   NaN         S
    644          645         1       3  ...  19.2583   NaN         C
    469          470         1       3  ...  19.2583   NaN         C
    78            79         1       2  ...  29.0000   NaN         S
    
    [5 rows x 12 columns] 
    
  • 我想根据舱位等级和年龄按降序对泰坦尼克号数据进行排序。

    In [7]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()
    Out[7]: 
     PassengerId  Survived  Pclass  ...    Fare Cabin  Embarked
    851          852         0       3  ...  7.7750   NaN         S
    116          117         0       3  ...  7.7500   NaN         Q
    280          281         0       3  ...  7.7500   NaN         Q
    483          484         1       3  ...  9.5875   NaN         S
    326          327         0       3  ...  6.2375   NaN         S
    
    [5 rows x 12 columns] 
    

    使用DataFrame.sort_values(),表格中的行根据定义的列进行排序。索引将遵循行顺序。

用户指南

有关表格排序的更多详细信息,请参阅用户指南中关于数据排序的部分。

从长表格格式到宽表格格式

让我们使用空气质量数据集的一个小子集。我们关注(NO_2)数据,并仅使用每个位置的前两个测量值(即每个组���头部)。数据子集将被称为no2_subset

# filter for no2 data only
In [8]: no2 = air_quality[air_quality["parameter"] == "no2"] 
# use 2 measurements (head) for each location (groupby)
In [9]: no2_subset = no2.sort_index().groupby(["location"]).head(2)

In [10]: no2_subset
Out[10]: 
 city country  ... value   unit
date.utc                                      ... 
2019-04-09 01:00:00+00:00  Antwerpen      BE  ...  22.5  µg/m³
2019-04-09 01:00:00+00:00      Paris      FR  ...  24.4  µg/m³
2019-04-09 02:00:00+00:00     London      GB  ...  67.0  µg/m³
2019-04-09 02:00:00+00:00  Antwerpen      BE  ...  53.5  µg/m³
2019-04-09 02:00:00+00:00      Paris      FR  ...  27.4  µg/m³
2019-04-09 03:00:00+00:00     London      GB  ...  67.0  µg/m³

[6 rows x 6 columns] 

../../_images/07_pivot.svg

  • 我想要三个站点的值分别作为相邻的列。

    In [11]: no2_subset.pivot(columns="location", values="value")
    Out[11]: 
    location                   BETR801  FR04014  London Westminster
    date.utc 
    2019-04-09 01:00:00+00:00     22.5     24.4                 NaN
    2019-04-09 02:00:00+00:00     53.5     27.4                67.0
    2019-04-09 03:00:00+00:00      NaN      NaN                67.0 
    

    pivot()函数纯粹是对数据的重新排列:每个索引/列组合需要一个单一值。

由于 pandas 支持多列绘图(参见绘图教程),因此从表格格式转换为表格格式可以同时绘制不同时间序列的图表:

In [12]: no2.head()
Out[12]: 
 city country location parameter  value   unit
date.utc 
2019-06-21 00:00:00+00:00  Paris      FR  FR04014       no2   20.0  µg/m³
2019-06-20 23:00:00+00:00  Paris      FR  FR04014       no2   21.8  µg/m³
2019-06-20 22:00:00+00:00  Paris      FR  FR04014       no2   26.5  µg/m³
2019-06-20 21:00:00+00:00  Paris      FR  FR04014       no2   24.9  µg/m³
2019-06-20 20:00:00+00:00  Paris      FR  FR04014       no2   21.4  µg/m³ 
In [13]: no2.pivot(columns="location", values="value").plot()
Out[13]: <Axes: xlabel='date.utc'> 

../../_images/7_reshape_columns.png

注意

当未定义index参数时,将使用现有索引(行标签)。

用户指南

有关pivot()的更多信息,请参阅用户指南中关于数据透视表对象的部分。

透视表

../../_images/07_pivot_table.svg

  • 我想要表格形式中每个站点的(NO_2)和(PM_{2.5})的平均浓度。

    In [14]: air_quality.pivot_table(
     ....:    values="value", index="location", columns="parameter", aggfunc="mean"
     ....: )
     ....: 
    Out[14]: 
    parameter                 no2       pm25
    location 
    BETR801             26.950920  23.169492
    FR04014             29.374284        NaN
    London Westminster  29.740050  13.443568 
    

    pivot()的情况下,数据只是重新排列。当需要聚合多个值(在这种特定情况下,不同时间步长上的值)时,可以使用pivot_table(),提供一个聚合函数(例如均值)来组合这些值。

透视表是电子表格软件中一个众所周知的概念。当对每个变量的行/列边距(小计)感兴趣时,请将margins参数设置为True

In [15]: air_quality.pivot_table(
 ....:    values="value",
 ....:    index="location",
 ....:    columns="parameter",
 ....:    aggfunc="mean",
 ....:    margins=True,
 ....: )
 ....: 
Out[15]: 
parameter                 no2       pm25        All
location 
BETR801             26.950920  23.169492  24.982353
FR04014             29.374284        NaN  29.374284
London Westminster  29.740050  13.443568  21.491708
All                 29.430316  14.386849  24.222743 

用户指南

有关pivot_table()的更多信息,请参阅用户指南中关于数据透视表的部分。

注意

如果你在想,pivot_table()确实直接与groupby()相关联。可以通过在parameterlocation上进行分组来得到相同的结果:

air_quality.groupby(["parameter", "location"])[["value"]].mean() 

转至用户指南

从宽格式到长格式

从前一节创建的宽格式表重新开始,我们使用reset_index()DataFrame添加新索引。

In [16]: no2_pivoted = no2.pivot(columns="location", values="value").reset_index()

In [17]: no2_pivoted.head()
Out[17]: 
location                  date.utc  BETR801  FR04014  London Westminster
0        2019-04-09 01:00:00+00:00     22.5     24.4                 NaN
1        2019-04-09 02:00:00+00:00     53.5     27.4                67.0
2        2019-04-09 03:00:00+00:00     54.5     34.2                67.0
3        2019-04-09 04:00:00+00:00     34.5     48.5                41.0
4        2019-04-09 05:00:00+00:00     46.5     59.5                41.0 

../../_images/07_melt.svg

  • 我想将所有空气质量(NO_2)测量值收集到单独的一列中(长格式)。

    In [18]: no_2 = no2_pivoted.melt(id_vars="date.utc")
    
    In [19]: no_2.head()
    Out[19]: 
     date.utc location  value
    0 2019-04-09 01:00:00+00:00  BETR801   22.5
    1 2019-04-09 02:00:00+00:00  BETR801   53.5
    2 2019-04-09 03:00:00+00:00  BETR801   54.5
    3 2019-04-09 04:00:00+00:00  BETR801   34.5
    4 2019-04-09 05:00:00+00:00  BETR801   46.5 
    

    DataFrame上调用pandas.melt()方法将数据表从宽格式转换为长格式。列标题变为新创建列中的变量名。

解决方案是如何应用pandas.melt()的简短版本。该方法将所有未在id_vars中提及的列融合成两列:一列是列标题名称,另一列是值本身。后一列默认名称为value

传递给pandas.melt()的参数可以更详细地定义:

In [20]: no_2 = no2_pivoted.melt(
 ....:    id_vars="date.utc",
 ....:    value_vars=["BETR801", "FR04014", "London Westminster"],
 ....:    value_name="NO_2",
 ....:    var_name="id_location",
 ....: )
 ....: 

In [21]: no_2.head()
Out[21]: 
 date.utc id_location  NO_2
0 2019-04-09 01:00:00+00:00     BETR801  22.5
1 2019-04-09 02:00:00+00:00     BETR801  53.5
2 2019-04-09 03:00:00+00:00     BETR801  54.5
3 2019-04-09 04:00:00+00:00     BETR801  34.5
4 2019-04-09 05:00:00+00:00     BETR801  46.5 

附加参数具有以下效果:

  • value_vars定义要融合在一起的列

  • value_name为值列提供自定义列名,而不是默认列名value

  • var_name为收集列标题名称的列提供自定义列名。否则,它将采用索引名称或默认值variable

因此,参数value_namevar_name只是两个生成列的用户定义名称。要融合的列由id_varsvalue_vars定义。

转至用户指南

使用pandas.melt()将数据从宽格式转换为长格式在用户指南中有详细说明,参见融合重塑部分。

记住

  • 支持按一个或多个列排序的sort_values

  • pivot函数纯粹是数据重构,pivot_table支持聚合。

  • pivot的反向操作(从长格式到宽格式)是melt(从宽格式到长格式)。

转至用户指南

用户指南中关于重塑和数据透视的页面提供了完整的概述。

排序表行

  • 我想根据乘客的年龄对泰坦尼克号数据进行排序。

    In [6]: titanic.sort_values(by="Age").head()
    Out[6]: 
     PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    803          804         1       3  ...   8.5167   NaN         C
    755          756         1       2  ...  14.5000   NaN         S
    644          645         1       3  ...  19.2583   NaN         C
    469          470         1       3  ...  19.2583   NaN         C
    78            79         1       2  ...  29.0000   NaN         S
    
    [5 rows x 12 columns] 
    
  • 我想根据船舱等级和年龄按降序对泰坦尼克号数据进行排序。

    In [7]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()
    Out[7]: 
     PassengerId  Survived  Pclass  ...    Fare Cabin  Embarked
    851          852         0       3  ...  7.7750   NaN         S
    116          117         0       3  ...  7.7500   NaN         Q
    280          281         0       3  ...  7.7500   NaN         Q
    483          484         1       3  ...  9.5875   NaN         S
    326          327         0       3  ...  6.2375   NaN         S
    
    [5 rows x 12 columns] 
    

    使用DataFrame.sort_values(),表中的行将根据定义的列进行排序。索引将遵循行顺序。

转到用户指南

有关表格排序的更多详细信息,请参阅用户指南中关于数据排序的部分。

从长表格格式到宽表格格式

让我们使用空气质量数据集的一个小子集。我们关注(NO_2)数据,并且只使用每个位置的前两次测量(即每个组的头部)。数据子集将被称为no2_subset

# filter for no2 data only
In [8]: no2 = air_quality[air_quality["parameter"] == "no2"] 
# use 2 measurements (head) for each location (groupby)
In [9]: no2_subset = no2.sort_index().groupby(["location"]).head(2)

In [10]: no2_subset
Out[10]: 
 city country  ... value   unit
date.utc                                      ... 
2019-04-09 01:00:00+00:00  Antwerpen      BE  ...  22.5  µg/m³
2019-04-09 01:00:00+00:00      Paris      FR  ...  24.4  µg/m³
2019-04-09 02:00:00+00:00     London      GB  ...  67.0  µg/m³
2019-04-09 02:00:00+00:00  Antwerpen      BE  ...  53.5  µg/m³
2019-04-09 02:00:00+00:00      Paris      FR  ...  27.4  µg/m³
2019-04-09 03:00:00+00:00     London      GB  ...  67.0  µg/m³

[6 rows x 6 columns] 

../../_images/07_pivot.svg

  • 我想要三个站点的值作为相邻的单独列��

    In [11]: no2_subset.pivot(columns="location", values="value")
    Out[11]: 
    location                   BETR801  FR04014  London Westminster
    date.utc 
    2019-04-09 01:00:00+00:00     22.5     24.4                 NaN
    2019-04-09 02:00:00+00:00     53.5     27.4                67.0
    2019-04-09 03:00:00+00:00      NaN      NaN                67.0 
    

    pivot()函数纯粹是对数据的重塑:每个索引/列组合需要一个单一值。

由于 pandas 支持多列的绘图(请参阅绘图教程),因此从表格格式转换为表格格式使得可以同时绘制不同时间序列:

In [12]: no2.head()
Out[12]: 
 city country location parameter  value   unit
date.utc 
2019-06-21 00:00:00+00:00  Paris      FR  FR04014       no2   20.0  µg/m³
2019-06-20 23:00:00+00:00  Paris      FR  FR04014       no2   21.8  µg/m³
2019-06-20 22:00:00+00:00  Paris      FR  FR04014       no2   26.5  µg/m³
2019-06-20 21:00:00+00:00  Paris      FR  FR04014       no2   24.9  µg/m³
2019-06-20 20:00:00+00:00  Paris      FR  FR04014       no2   21.4  µg/m³ 
In [13]: no2.pivot(columns="location", values="value").plot()
Out[13]: <Axes: xlabel='date.utc'> 

../../_images/7_reshape_columns.png

注意

当未定义index参数时,将使用现有的索引(行标签)。

转到用户指南

有关pivot()的更多信息,请参阅用户指南中关于数据透视表 DataFrame 对象的部分。

数据透视表

../../_images/07_pivot_table.svg

  • 我想要每个站点中(NO_2)和(PM_{2.5})的平均浓度以表格形式呈现。

    In [14]: air_quality.pivot_table(
     ....:    values="value", index="location", columns="parameter", aggfunc="mean"
     ....: )
     ....: 
    Out[14]: 
    parameter                 no2       pm25
    location 
    BETR801             26.950920  23.169492
    FR04014             29.374284        NaN
    London Westminster  29.740050  13.443568 
    

    pivot()的情况下,数据仅被重新排列。当需要聚合多个值(在这种特定情况下,不同时间步的值)时,可以使用pivot_table(),提供一个聚合函数(例如平均值)来组合这些值。

数据透视表是电子表格软件中一个众所周知的概念。当对每个变量的行/列边距(小计)感兴趣时,请将margins参数设置为True

In [15]: air_quality.pivot_table(
 ....:    values="value",
 ....:    index="location",
 ....:    columns="parameter",
 ....:    aggfunc="mean",
 ....:    margins=True,
 ....: )
 ....: 
Out[15]: 
parameter                 no2       pm25        All
location 
BETR801             26.950920  23.169492  24.982353
FR04014             29.374284        NaN  29.374284
London Westminster  29.740050  13.443568  21.491708
All                 29.430316  14.386849  24.222743 

转到用户指南

欲了解有关pivot_table()的更多信息,请参阅用户指南中关于数据透视表的部分。

注意

如果你在想,pivot_table()确实直接链接到groupby()。相同的结果可以通过在parameterlocation上进行分组来得到:

air_quality.groupby(["parameter", "location"])[["value"]].mean() 

转到用户指南

宽到长格式

从前一节创建的宽格式表重新开始,我们使用reset_index()DataFrame添加新索引。

In [16]: no2_pivoted = no2.pivot(columns="location", values="value").reset_index()

In [17]: no2_pivoted.head()
Out[17]: 
location                  date.utc  BETR801  FR04014  London Westminster
0        2019-04-09 01:00:00+00:00     22.5     24.4                 NaN
1        2019-04-09 02:00:00+00:00     53.5     27.4                67.0
2        2019-04-09 03:00:00+00:00     54.5     34.2                67.0
3        2019-04-09 04:00:00+00:00     34.5     48.5                41.0
4        2019-04-09 05:00:00+00:00     46.5     59.5                41.0 

../../_images/07_melt.svg

  • 我想将所有空气质量(\(NO_2\))测量值收集到单独的一列中(长格式)。

    In [18]: no_2 = no2_pivoted.melt(id_vars="date.utc")
    
    In [19]: no_2.head()
    Out[19]: 
     date.utc location  value
    0 2019-04-09 01:00:00+00:00  BETR801   22.5
    1 2019-04-09 02:00:00+00:00  BETR801   53.5
    2 2019-04-09 03:00:00+00:00  BETR801   54.5
    3 2019-04-09 04:00:00+00:00  BETR801   34.5
    4 2019-04-09 05:00:00+00:00  BETR801   46.5 
    

    pandas.melt()方法在DataFrame上将数据表从宽格式转换为长格式。列标题变为新创建列中的变量名称。

解决方案是如何应用pandas.melt()的简短版本。该方法将未在id_vars中提及的所有列融合到两列中:一列是列标题名称,另一列是值本身。后一列默认命名为value

传递给pandas.melt()的参数可以更详细地定义:

In [20]: no_2 = no2_pivoted.melt(
 ....:    id_vars="date.utc",
 ....:    value_vars=["BETR801", "FR04014", "London Westminster"],
 ....:    value_name="NO_2",
 ....:    var_name="id_location",
 ....: )
 ....: 

In [21]: no_2.head()
Out[21]: 
 date.utc id_location  NO_2
0 2019-04-09 01:00:00+00:00     BETR801  22.5
1 2019-04-09 02:00:00+00:00     BETR801  53.5
2 2019-04-09 03:00:00+00:00     BETR801  54.5
3 2019-04-09 04:00:00+00:00     BETR801  34.5
4 2019-04-09 05:00:00+00:00     BETR801  46.5 

附加参数具有以下效果:

  • value_vars定义要融合在一起的列

  • value_name为值列提供自定义列名,而不是默认列名value

  • var_name为收集列标题名称的列提供自定义列名。否则,它将采用索引名称或默认的variable

因此,参数value_namevar_name只是生成的用户定义列 ocolumns 的名称。要融合的列由id_varsvalue_vars定义。

转到用户指南

使用pandas.melt()从宽格式转换为长格式在用户指南中有详细说明,参见通过 melt 进行重塑部分。

记住

  • 通过sort_values支持按一个或多个列进行排序。

  • pivot函数纯粹是数据重构,pivot_table支持聚合。

  • pivot的反向(从长到宽格式)是melt(从宽到长格式)。

转到用户指南

完整概述可在关于重塑和旋转的用户指南页面上找到。

如何合并来自多个表的数据

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/08_combine_dataframes.html

连接对象

../../_images/08_concat_row.svg

  • 我想将(NO_2)和(PM_{25})的测量数据,两个结构相似的表,合并到一个表中。

    In [8]: air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)
    
    In [9]: air_quality.head()
    Out[9]: 
     date.utc location parameter  value
    0  2019-06-18 06:00:00+00:00  BETR801      pm25   18.0
    1  2019-06-17 08:00:00+00:00  BETR801      pm25    6.5
    2  2019-06-17 07:00:00+00:00  BETR801      pm25   18.5
    3  2019-06-17 06:00:00+00:00  BETR801      pm25   16.0
    4  2019-06-17 05:00:00+00:00  BETR801      pm25    7.5 
    

    concat()函数执行多个表沿一个轴(行或列)的连接操作。

默认情况下,沿轴 0 进行连接,因此结果表合并了输入表的行。让我们检查原始表和连接表的形状以验证操作:

In [10]: print('Shape of the ``air_quality_pm25`` table: ', air_quality_pm25.shape)
Shape of the ``air_quality_pm25`` table:  (1110, 4)

In [11]: print('Shape of the ``air_quality_no2`` table: ', air_quality_no2.shape)
Shape of the ``air_quality_no2`` table:  (2068, 4)

In [12]: print('Shape of the resulting ``air_quality`` table: ', air_quality.shape)
Shape of the resulting ``air_quality`` table:  (3178, 4) 

因此,结果表有 3178 行= 1110 + 2068 行。

注意

axis参数将返回可以沿着应用的多个 pandas 方法。DataFrame有两个对应的轴:第一个沿着行垂直向下运行(轴 0),第二个沿着列水平运行(轴 1)。大多数操作(如连接或汇总统计)默认跨行(轴 0),但也可以跨列应用。

根据日期时间信息对表进行排序也说明了两个表的组合,parameter列定义了表的来源(来自air_quality_no2表的no2或来自air_quality_pm25表的pm25):

In [13]: air_quality = air_quality.sort_values("date.utc")

In [14]: air_quality.head()
Out[14]: 
 date.utc            location parameter  value
2067  2019-05-07 01:00:00+00:00  London Westminster       no2   23.0
1003  2019-05-07 01:00:00+00:00             FR04014       no2   25.0
100   2019-05-07 01:00:00+00:00             BETR801      pm25   12.5
1098  2019-05-07 01:00:00+00:00             BETR801       no2   50.5
1109  2019-05-07 01:00:00+00:00  London Westminster      pm25    8.0 

在这个具体的例子中,数据提供的parameter列确保可以识别原始表中的每个表。这并不总是这样。concat函数提供了一个方便的解决方案,使用keys参数添加一个额外的(分层)行索引。例如:

In [15]: air_quality_ = pd.concat([air_quality_pm25, air_quality_no2], keys=["PM25", "NO2"])

In [16]: air_quality_.head()
Out[16]: 
 date.utc location parameter  value
PM25 0  2019-06-18 06:00:00+00:00  BETR801      pm25   18.0
 1  2019-06-17 08:00:00+00:00  BETR801      pm25    6.5
 2  2019-06-17 07:00:00+00:00  BETR801      pm25   18.5
 3  2019-06-17 06:00:00+00:00  BETR801      pm25   16.0
 4  2019-06-17 05:00:00+00:00  BETR801      pm25    7.5 

注意

在这些教程中尚未提到同时存在多个行/列索引。分层索引MultiIndex是一个用于分析更高维数据的高级且强大的 pandas 功能。

多重索引超出了本 pandas 入门范围。暂时记住函数reset_index可以用于将索引的任何级别转换为列,例如air_quality.reset_index(level=0)

到用户指南

随意深入探讨高级索引用户指南部分中的多重索引世界。

到用户指南

在对象连接部分提供了有关表连接(行和列连接)的更多选项以及如何使用concat定义在其他轴上的索引逻辑(并集或交集)。

使用共同标识符连接表

../../_images/08_merge_left.svg

  • 将由站点元数据表提供的站点坐标添加到测量表中的相应行。

    警告

    空气质量测量站坐标存储在数据文件air_quality_stations.csv中,使用py-openaq包下载。

    In [17]: stations_coord = pd.read_csv("data/air_quality_stations.csv")
    
    In [18]: stations_coord.head()
    Out[18]: 
     location  coordinates.latitude  coordinates.longitude
    0  BELAL01              51.23619                4.38522
    1  BELHB23              51.17030                4.34100
    2  BELLD01              51.10998                5.00486
    3  BELLD02              51.12038                5.02155
    4  BELR833              51.32766                4.36226 
    

    注意

    此示例中使用的站点(FR04014、BETR801 和 London Westminster)只是元数据表中列出的三个条目。我们只想将这三个站点的坐标添加到测量表中,每个站点对应air_quality表的相应行。

    In [19]: air_quality.head()
    Out[19]: 
     date.utc            location parameter  value
    2067  2019-05-07 01:00:00+00:00  London Westminster       no2   23.0
    1003  2019-05-07 01:00:00+00:00             FR04014       no2   25.0
    100   2019-05-07 01:00:00+00:00             BETR801      pm25   12.5
    1098  2019-05-07 01:00:00+00:00             BETR801       no2   50.5
    1109  2019-05-07 01:00:00+00:00  London Westminster      pm25    8.0 
    
    In [20]: air_quality = pd.merge(air_quality, stations_coord, how="left", on="location")
    
    In [21]: air_quality.head()
    Out[21]: 
     date.utc  ... coordinates.longitude
    0  2019-05-07 01:00:00+00:00  ...              -0.13193
    1  2019-05-07 01:00:00+00:00  ...               2.39390
    2  2019-05-07 01:00:00+00:00  ...               2.39390
    3  2019-05-07 01:00:00+00:00  ...               4.43182
    4  2019-05-07 01:00:00+00:00  ...               4.43182
    
    [5 rows x 6 columns] 
    

    使用merge()函数,对于air_quality表中的每一行,从air_quality_stations_coord表中添加相应的坐标。这两个表都有一个共同的location列,用作组合信息的键。通过选择left连接,最终表中只包含air_quality(左)表中可用的位置,即 FR04014、BETR801 和 London Westminster。merge函数支持类似数据库风格操作的多个连接选项。

  • 将参数元数据表提供的参数完整描述和名称添加到测量表中。

    警告

    空气质量参数元数据存储在数据文件air_quality_parameters.csv中,使用py-openaq包下载。

    In [22]: air_quality_parameters = pd.read_csv("data/air_quality_parameters.csv")
    
    In [23]: air_quality_parameters.head()
    Out[23]: 
     id                                        description  name
    0    bc                                       Black Carbon    BC
    1    co                                    Carbon Monoxide    CO
    2   no2                                   Nitrogen Dioxide   NO2
    3    o3                                              Ozone    O3
    4  pm10  Particulate matter less than 10 micrometers in...  PM10 
    
    In [24]: air_quality = pd.merge(air_quality, air_quality_parameters,
     ....:                       how='left', left_on='parameter', right_on='id')
     ....: 
    
    In [25]: air_quality.head()
    Out[25]: 
     date.utc  ...   name
    0  2019-05-07 01:00:00+00:00  ...    NO2
    1  2019-05-07 01:00:00+00:00  ...    NO2
    2  2019-05-07 01:00:00+00:00  ...    NO2
    3  2019-05-07 01:00:00+00:00  ...  PM2.5
    4  2019-05-07 01:00:00+00:00  ...    NO2
    
    [5 rows x 9 columns] 
    

    与前面的示例相比,没有共同的列名。但是,在air_quality表中的parameter列和air_quality_parameters_name中的id列都以共同格式提供了测量变量。这里使用left_onright_on参数(而不仅仅是on)来建立两个表之间的链接。

用户指南

pandas 还支持内部、外部和右连接。有关表的连接/合并的更多信息,请参阅用户指南中关于数据库风格表合并的部分。或者查看与 SQL 的比较页面。

记住

  • 可以使用concat函数沿着列或行将多个表连接起来。

  • 对于类似数据库的表合并/连接,请使用merge函数。

用户指南

查看用户指南,了解各种合并数据表的方法的详细描述。

连接对象

../../_images/08_concat_row.svg

  • 我想将(NO_2)和(PM_{25})的测量值,两个结构相似的表,合并到一个表中。

    In [8]: air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)
    
    In [9]: air_quality.head()
    Out[9]: 
     date.utc location parameter  value
    0  2019-06-18 06:00:00+00:00  BETR801      pm25   18.0
    1  2019-06-17 08:00:00+00:00  BETR801      pm25    6.5
    2  2019-06-17 07:00:00+00:00  BETR801      pm25   18.5
    3  2019-06-17 06:00:00+00:00  BETR801      pm25   16.0
    4  2019-06-17 05:00:00+00:00  BETR801      pm25    7.5 
    

    concat()函数执行多个表沿一个轴(行或列)的连接操作。

默认情况下,沿轴 0 进行连接,因此生成的表将合并输入表的行。让我们检查原始表和连接表的形状以验证操作:

In [10]: print('Shape of the ``air_quality_pm25`` table: ', air_quality_pm25.shape)
Shape of the ``air_quality_pm25`` table:  (1110, 4)

In [11]: print('Shape of the ``air_quality_no2`` table: ', air_quality_no2.shape)
Shape of the ``air_quality_no2`` table:  (2068, 4)

In [12]: print('Shape of the resulting ``air_quality`` table: ', air_quality.shape)
Shape of the resulting ``air_quality`` table:  (3178, 4) 

因此,结果表有 3178 = 1110 + 2068 行。

注意

axis参数将返回一些可以沿着轴应用的 pandas 方法。DataFrame有两个对应的轴:第一个沿着行垂直向下运行(轴 0),第二个沿着列水平运行(轴 1)。大多数操作(如连接或汇总统计)默认是沿着行(轴 0)进行的,但也可以沿着列进行。

根据日期时间信息对表进行排序也说明了两个表的组合,其中parameter列定义了表的来源(air_quality_no2表中的no2air_quality_pm25表中的pm25):

In [13]: air_quality = air_quality.sort_values("date.utc")

In [14]: air_quality.head()
Out[14]: 
 date.utc            location parameter  value
2067  2019-05-07 01:00:00+00:00  London Westminster       no2   23.0
1003  2019-05-07 01:00:00+00:00             FR04014       no2   25.0
100   2019-05-07 01:00:00+00:00             BETR801      pm25   12.5
1098  2019-05-07 01:00:00+00:00             BETR801       no2   50.5
1109  2019-05-07 01:00:00+00:00  London Westminster      pm25    8.0 

在这个特定示例中,数据提供的parameter列确保可以识别原始表中的每个表。这并非总是如此。concat函数提供了一个方便的解决方案,使用keys参数添加一个额外的(分层)行索引。例如:

In [15]: air_quality_ = pd.concat([air_quality_pm25, air_quality_no2], keys=["PM25", "NO2"])

In [16]: air_quality_.head()
Out[16]: 
 date.utc location parameter  value
PM25 0  2019-06-18 06:00:00+00:00  BETR801      pm25   18.0
 1  2019-06-17 08:00:00+00:00  BETR801      pm25    6.5
 2  2019-06-17 07:00:00+00:00  BETR801      pm25   18.5
 3  2019-06-17 06:00:00+00:00  BETR801      pm25   16.0
 4  2019-06-17 05:00:00+00:00  BETR801      pm25    7.5 

注意

在这些教程中没有提到同时存在多个行/列索引。层次化索引MultiIndex是用于分析高维数据的高级且强大的 pandas 功能。

多重索引超出了本 pandas 介绍的范围。暂时记住函数reset_index可用于将索引的任何级别转换为列,例如air_quality.reset_index(level=0)

用户指南

随时深入研究用户指南中关于高级索引的多重索引世界。

用户指南

提供了有关表连接的更多选项(按行和列)以及如何使用concat来定义索引在其他轴上的逻辑(并集或交集)的信息,请参阅对象连接部分。

使用共同标识符连接表

../../_images/08_merge_left.svg

  • 将由站点元数据表提供的站点坐标添加到测量表中的相应行中。

    警告

    空气质量测量站点坐标存储在数据文件air_quality_stations.csv中,使用py-openaq包下载。

    In [17]: stations_coord = pd.read_csv("data/air_quality_stations.csv")
    
    In [18]: stations_coord.head()
    Out[18]: 
     location  coordinates.latitude  coordinates.longitude
    0  BELAL01              51.23619                4.38522
    1  BELHB23              51.17030                4.34100
    2  BELLD01              51.10998                5.00486
    3  BELLD02              51.12038                5.02155
    4  BELR833              51.32766                4.36226 
    

    注意

    此示例中使用的站点(FR04014、BETR801 和 London Westminster)只是元数据表中列出的三个条目。我们只想将这三个站点的坐标添加到测量表中,每个站点对应air_quality表的相应行。

    In [19]: air_quality.head()
    Out[19]: 
     date.utc            location parameter  value
    2067  2019-05-07 01:00:00+00:00  London Westminster       no2   23.0
    1003  2019-05-07 01:00:00+00:00             FR04014       no2   25.0
    100   2019-05-07 01:00:00+00:00             BETR801      pm25   12.5
    1098  2019-05-07 01:00:00+00:00             BETR801       no2   50.5
    1109  2019-05-07 01:00:00+00:00  London Westminster      pm25    8.0 
    
    In [20]: air_quality = pd.merge(air_quality, stations_coord, how="left", on="location")
    
    In [21]: air_quality.head()
    Out[21]: 
     date.utc  ... coordinates.longitude
    0  2019-05-07 01:00:00+00:00  ...              -0.13193
    1  2019-05-07 01:00:00+00:00  ...               2.39390
    2  2019-05-07 01:00:00+00:00  ...               2.39390
    3  2019-05-07 01:00:00+00:00  ...               4.43182
    4  2019-05-07 01:00:00+00:00  ...               4.43182
    
    [5 rows x 6 columns] 
    

    使用merge()函数,对于air_quality表中的每一行,从air_quality_stations_coord表中添加相应的坐标。这两个表格都有一个名为location的列,用作合并信息的关键。通过选择left连接,只有在air_quality(左)表中可用的位置,即 FR04014、BETR801 和 London Westminster,最终出现在结果表中。merge函数支持类似数据库操作的多个连接选项。

  • 将参数元数据表提供的参数完整描述和名称添加到测量表中。

    警告

    空气质量参数元数据存储在数据文件air_quality_parameters.csv中,使用py-openaq包下载。

    In [22]: air_quality_parameters = pd.read_csv("data/air_quality_parameters.csv")
    
    In [23]: air_quality_parameters.head()
    Out[23]: 
     id                                        description  name
    0    bc                                       Black Carbon    BC
    1    co                                    Carbon Monoxide    CO
    2   no2                                   Nitrogen Dioxide   NO2
    3    o3                                              Ozone    O3
    4  pm10  Particulate matter less than 10 micrometers in...  PM10 
    
    In [24]: air_quality = pd.merge(air_quality, air_quality_parameters,
     ....:                       how='left', left_on='parameter', right_on='id')
     ....: 
    
    In [25]: air_quality.head()
    Out[25]: 
     date.utc  ...   name
    0  2019-05-07 01:00:00+00:00  ...    NO2
    1  2019-05-07 01:00:00+00:00  ...    NO2
    2  2019-05-07 01:00:00+00:00  ...    NO2
    3  2019-05-07 01:00:00+00:00  ...  PM2.5
    4  2019-05-07 01:00:00+00:00  ...    NO2
    
    [5 rows x 9 columns] 
    

    与前面的示例相比,这里没有共同的列名。然而,在air_quality表中的parameter列和air_quality_parameters_name中的id列都以共同的格式提供了测量变量。这里使用left_onright_on参数(而不仅仅是on)来建立两个表格之间的链接。

至用户指南

pandas 还支持内部、外部和右连接。有关表格连接/合并的更多信息,请参阅用户指南中关于数据库风格表格合并的部分。或查看与 SQL 的比较页面。

记住

  • 可以使用concat函数在列方向和行方向上连接多个表格。

  • 对于类似数据库的表格合并/连接,请使用merge函数。

至用户指南

请参阅用户指南,了解各种数据表合并设施的详细描述。

如何轻松处理时间序列数据

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/09_timeseries.html

使用 pandas 日期时间属性

  • 我想将列datetime中的日期作为日期对象而不是纯文本来处理

    In [7]: air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
    
    In [8]: air_quality["datetime"]
    Out[8]: 
    0      2019-06-21 00:00:00+00:00
    1      2019-06-20 23:00:00+00:00
    2      2019-06-20 22:00:00+00:00
    3      2019-06-20 21:00:00+00:00
    4      2019-06-20 20:00:00+00:00
     ... 
    2063   2019-05-07 06:00:00+00:00
    2064   2019-05-07 04:00:00+00:00
    2065   2019-05-07 03:00:00+00:00
    2066   2019-05-07 02:00:00+00:00
    2067   2019-05-07 01:00:00+00:00
    Name: datetime, Length: 2068, dtype: datetime64[ns, UTC] 
    

    最初,datetime中的值是字符字符串,不提供任何日期时间操作(例如提取年份、星期几等)。通过应用to_datetime函数,pandas 解释这些字符串并将其转换为日期时间(即datetime64[ns, UTC])对象。在 pandas 中,我们将这些日期时间对象称为类似于标准库中的datetime.datetimepandas.Timestamp

注意

由于许多数据集中的一列包含日期时间信息,pandas 输入函数如pandas.read_csv()pandas.read_json()在读取数据时可以使用parse_dates参数和要读取为 Timestamp 的列的列表进行日期转换:

pd.read_csv("../data/air_quality_no2_long.csv", parse_dates=["datetime"]) 

这些pandas.Timestamp对象有什么用?让我们通过一些示例案例来说明其附加值。

我们正在处理的时间序列数据集的开始和结束日期是什么?

In [9]: air_quality["datetime"].min(), air_quality["datetime"].max()
Out[9]: 
(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
 Timestamp('2019-06-21 00:00:00+0000', tz='UTC')) 

使用pandas.Timestamp处理日期时间使我们能够计算日期信息并使其可比较。因此,我们可以用这个来获取时间序列的长度:

In [10]: air_quality["datetime"].max() - air_quality["datetime"].min()
Out[10]: Timedelta('44 days 23:00:00') 

结果是一个类似于标准 Python 库中的datetime.timedeltapandas.Timedelta对象,定义了一个时间持续。

转到用户指南

pandas 支持的各种时间概念在用户指南的时间相关概念部分中有解释。

  • 我想向DataFrame添加一个只包含测量月份的新列

    In [11]: air_quality["month"] = air_quality["datetime"].dt.month
    
    In [12]: air_quality.head()
    Out[12]: 
     city country                  datetime  ... value   unit  month
    0  Paris      FR 2019-06-21 00:00:00+00:00  ...  20.0  µg/m³      6
    1  Paris      FR 2019-06-20 23:00:00+00:00  ...  21.8  µg/m³      6
    2  Paris      FR 2019-06-20 22:00:00+00:00  ...  26.5  µg/m³      6
    3  Paris      FR 2019-06-20 21:00:00+00:00  ...  24.9  µg/m³      6
    4  Paris      FR 2019-06-20 20:00:00+00:00  ...  21.4  µg/m³      6
    
    [5 rows x 8 columns] 
    

    通过使用日期的Timestamp对象,pandas 提供了许多与时间相关的属性。例如month,还有yearquarter���。所有这些属性都可以通过dt访问器访问。

转到用户指南

现有日期属性的概述在时间和日期组件概述表中给出。关于dt访问器返回类似日期时间的属性的更多细节在 dt 访问器的专用部分中有解释。

  • 每天每个测量位置的平均(NO_2)浓度是多少?

    In [13]: air_quality.groupby(
     ....:    [air_quality["datetime"].dt.weekday, "location"])["value"].mean()
     ....: 
    Out[13]: 
    datetime  location 
    0         BETR801               27.875000
     FR04014               24.856250
     London Westminster    23.969697
    1         BETR801               22.214286
     FR04014               30.999359
     ... 
    5         FR04014               25.266154
     London Westminster    24.977612
    6         BETR801               21.896552
     FR04014               23.274306
     London Westminster    24.859155
    Name: value, Length: 21, dtype: float64 
    

    还记得来自统计计算教程的groupby提供的分割-应用-合并模式吗?在这里,我们想要计算给定统计量(例如均值(NO_2))每个工作日每个测量位置的数据。为了按工作日分组,我们使用 pandas Timestamp 的 datetime 属性weekday(星期一=0,星期日=6),该属性也可以通过dt访问器访问。可以对位置和工作日进行分组,以便在每个组合上分割均值的计算。

    危险

    由于在这些示例中我们使用的是非常短的时间序列,因此分析结果并不代表长期结果!

  • 绘制所有站点时间序列中一天内的典型(NO_2)模式。换句话说,每小时的平均值是多少?

    In [14]: fig, axs = plt.subplots(figsize=(12, 4))
    
    In [15]: air_quality.groupby(air_quality["datetime"].dt.hour)["value"].mean().plot(
     ....:    kind='bar', rot=0, ax=axs
     ....: )
     ....: 
    Out[15]: <Axes: xlabel='datetime'>
    
    In [16]: plt.xlabel("Hour of the day");  # custom x label using Matplotlib
    
    In [17]: plt.ylabel("$NO_2 (µg/m³)$"); 
    

    ../../_images/09_bar_chart.png

    与前一个案例类似,我们想要计算给定统计量(例如均值(NO_2))每小时的数据,并且我们可以再次使用分割-应用-合并的方法。对于这种情况,我们使用 pandas Timestamp 的 datetime 属性hour,该属性也可以通过dt访问器访问。

日期时间作为索引

在重塑教程中,介绍了pivot()用于将数据表重塑,使每个测量位置成为单独的列:

In [18]: no_2 = air_quality.pivot(index="datetime", columns="location", values="value")

In [19]: no_2.head()
Out[19]: 
location                   BETR801  FR04014  London Westminster
datetime 
2019-05-07 01:00:00+00:00     50.5     25.0                23.0
2019-05-07 02:00:00+00:00     45.0     27.7                19.0
2019-05-07 03:00:00+00:00      NaN     50.4                19.0
2019-05-07 04:00:00+00:00      NaN     61.9                16.0
2019-05-07 05:00:00+00:00      NaN     72.4                 NaN 

注意

通过数据透视,日期时间信息成为表格的索引。通常,通过set_index函数可以将列设置为索引。

使用日期时间索引(即DatetimeIndex)提供了强大的功能。例如,我们不需要dt访问器来获取时间序列属性,而是直接在索引上可用这些属性:

In [20]: no_2.index.year, no_2.index.weekday
Out[20]: 
(Index([2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019,
 ...
 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019],
 dtype='int32', name='datetime', length=1033),
 Index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 ...
 3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
 dtype='int32', name='datetime', length=1033)) 

其他一些优点包括方便的时间段子集或图表上的调整时间刻度。让我们在我们的数据上应用这个。

  • 创建一个图表,显示从 5 月 20 日到 5 月 21 日结束的不同站点的(NO_2)值

    In [21]: no_2["2019-05-20":"2019-05-21"].plot(); 
    

    ../../_images/09_time_section.png

    通过提供一个解析为日期时间的字符串,可以在DatetimeIndex上选择特定的数据子集。

用户指南

有关DatetimeIndex和使用字符串进行切片的更多信息,请参阅时间序列索引部分。

将时间序列重新采样为另一个频率

  • 将当前每小时时间序列值聚合到每个站点的月最大值。

    In [22]: monthly_max = no_2.resample("ME").max()
    
    In [23]: monthly_max
    Out[23]: 
    location                   BETR801  FR04014  London Westminster
    datetime 
    2019-05-31 00:00:00+00:00     74.5     97.0                97.0
    2019-06-30 00:00:00+00:00     52.5     84.7                52.0 
    

    在具有日期时间索引的时间序列数据上,一种非常强大的方法是能够将时间序列重采样()到另一个频率(例如,将每秒数据转换为每 5 分钟数据)。

resample()方法类似于分组操作:

  • 它提供基于时间的分组,通过使用定义目标频率的字符串(例如M5H,...)

  • 它需要聚合函数,如meanmax

到用户指南

有关用于定义时间序列频率的别名的概述可在偏移别名概述表中找到。

在定义时,时间序列的频率由freq属性提供:

In [24]: monthly_max.index.freq
Out[24]: <MonthEnd> 
  • 绘制每个站点每日平均(NO_2)值的图表。

    In [25]: no_2.resample("D").mean().plot(style="-o", figsize=(10, 5)); 
    

    ../../_images/09_resample_mean.png

到用户指南

有关时间序列重采样强大功能的更多细节,请参阅用户指南中关于重采样的部分。

记住

  • 有效的日期字符串可以使用to_datetime函数或作为读取函数的一部分转换为日期时间对象。

  • pandas 中的日期时间对象支持计算、逻辑操作和使用dt访问器的便捷日期相关属性。

  • DatetimeIndex包含这些与日期相关的属性,并支持便捷的切片。

  • 重采样是一种强大的方法,可以改变时间序列的频率。

到用户指南

有关时间序列的完整概述可在时间序列和日期功能页面上找到。

使用 pandas 日期时间属性

  • 我想要将列datetime中的日期作为日期时间对象而不是纯文本进行处理

    In [7]: air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
    
    In [8]: air_quality["datetime"]
    Out[8]: 
    0      2019-06-21 00:00:00+00:00
    1      2019-06-20 23:00:00+00:00
    2      2019-06-20 22:00:00+00:00
    3      2019-06-20 21:00:00+00:00
    4      2019-06-20 20:00:00+00:00
     ... 
    2063   2019-05-07 06:00:00+00:00
    2064   2019-05-07 04:00:00+00:00
    2065   2019-05-07 03:00:00+00:00
    2066   2019-05-07 02:00:00+00:00
    2067   2019-05-07 01:00:00+00:00
    Name: datetime, Length: 2068, dtype: datetime64[ns, UTC] 
    

    最初,datetime中的值是字符字符串,不提供任何日期时间操作(例如提取年份、星期几等)。通过应用to_datetime函数,pandas 解释这些字符串并将其转换为日期时间(即datetime64[ns, UTC])对象。在 pandas 中,我们将这些日期时间对象称为类似于标准库中的datetime.datetimepandas.Timestamp

注意

由于许多数据集中的一列包含日期时间信息,因此 pandas 输入函数如pandas.read_csv()pandas.read_json()在读取数据时可以使用parse_dates参数进行日期转换,参数是要读取为时间戳的列的列表:

pd.read_csv("../data/air_quality_no2_long.csv", parse_dates=["datetime"]) 

这些pandas.Timestamp对象有什么用?让我们通过一些示例案例来说明其附加值。

我们正在处理的时间序列数据集的开始和结束日期是什么?

In [9]: air_quality["datetime"].min(), air_quality["datetime"].max()
Out[9]: 
(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
 Timestamp('2019-06-21 00:00:00+0000', tz='UTC')) 

使用pandas.Timestamp来处理日期时间使我们能够计算日期信息并使其可比较。因此,我们可以用它来获取时间序列的长度:

In [10]: air_quality["datetime"].max() - air_quality["datetime"].min()
Out[10]: Timedelta('44 days 23:00:00') 

结果是一个pandas.Timedelta对象,类似于标准 Python 库中的datetime.timedelta,定义了时间持续。

用户指南

pandas 支持的各种时间概念在时间相关概念的用户指南部分有详细解释。

  • 我想要向DataFrame添加一个只包含测量月份的新列

    In [11]: air_quality["month"] = air_quality["datetime"].dt.month
    
    In [12]: air_quality.head()
    Out[12]: 
     city country                  datetime  ... value   unit  month
    0  Paris      FR 2019-06-21 00:00:00+00:00  ...  20.0  µg/m³      6
    1  Paris      FR 2019-06-20 23:00:00+00:00  ...  21.8  µg/m³      6
    2  Paris      FR 2019-06-20 22:00:00+00:00  ...  26.5  µg/m³      6
    3  Paris      FR 2019-06-20 21:00:00+00:00  ...  24.9  µg/m³      6
    4  Paris      FR 2019-06-20 20:00:00+00:00  ...  21.4  µg/m³      6
    
    [5 rows x 8 columns] 
    

    通过使用Timestamp对象作为日期,pandas 提供了许多与时间相关的属性。例如month,还有yearquarter等等。所有这些属性都可以通过dt访问器访问。

用户指南

时间和日期组件概览表中提供了现有日期属性的概述。关于dt访问器返回类似日期时间属性的更多细节在 dt 访问器的专门部分有解释。

  • 每周每天每个测量位置的平均(NO_2)浓度是多少?

    In [13]: air_quality.groupby(
     ....:    [air_quality["datetime"].dt.weekday, "location"])["value"].mean()
     ....: 
    Out[13]: 
    datetime  location 
    0         BETR801               27.875000
     FR04014               24.856250
     London Westminster    23.969697
    1         BETR801               22.214286
     FR04014               30.999359
     ... 
    5         FR04014               25.266154
     London Westminster    24.977612
    6         BETR801               21.896552
     FR04014               23.274306
     London Westminster    24.859155
    Name: value, Length: 21, dtype: float64 
    

    还记得groupby提供的分割-应用-合并模式吗?在统计计算教程中,我们想要计算每个工作日和每个测量位置的给定统计量(例如平均(NO_2))。为了按工作日分组,我们使用 pandas Timestamp的日期时间属性weekday(星期一=0,星期日=6),这也可以通过dt访问器访问。可以对位置和工作日进行分组,以便在这些组合中分别计算平均值。

    危险

    在这些示例中,我们处理的时间序列非常短,分析结果并不提供长期代表性的结果!

  • 绘制我们所有站点时间序列中一天内典型的(NO_2)模式。换句话说,每个小时的平均值是多少?

    In [14]: fig, axs = plt.subplots(figsize=(12, 4))
    
    In [15]: air_quality.groupby(air_quality["datetime"].dt.hour)["value"].mean().plot(
     ....:    kind='bar', rot=0, ax=axs
     ....: )
     ....: 
    Out[15]: <Axes: xlabel='datetime'>
    
    In [16]: plt.xlabel("Hour of the day");  # custom x label using Matplotlib
    
    In [17]: plt.ylabel("$NO_2 (µg/m³)$"); 
    

    ../../_images/09_bar_chart.png

    类似于前面的情况,我们想要计算每个小时的给定统计量(例如平均(NO_2)),我们可以再次使用分割-应用-合并方法。对于这种情况,我们使用 pandas Timestamp的日期时间属性hour,这也可以通过dt访问器访问。

日期时间作为索引

在重塑教程中,介绍了使用pivot()来将数据表重塑,使每个测量位置成为单独的列:

In [18]: no_2 = air_quality.pivot(index="datetime", columns="location", values="value")

In [19]: no_2.head()
Out[19]: 
location                   BETR801  FR04014  London Westminster
datetime 
2019-05-07 01:00:00+00:00     50.5     25.0                23.0
2019-05-07 02:00:00+00:00     45.0     27.7                19.0
2019-05-07 03:00:00+00:00      NaN     50.4                19.0
2019-05-07 04:00:00+00:00      NaN     61.9                16.0
2019-05-07 05:00:00+00:00      NaN     72.4                 NaN 

注意

通过数据透视,日期时间信息成为表的索引。通常,通过set_index函数可以将列设置为索引。

使用日期时间索引(即DatetimeIndex)提供了强大的功���。例如,我们不需要dt访问器来获取时间序列属性,而是直接在索引上可用这些属性:

In [20]: no_2.index.year, no_2.index.weekday
Out[20]: 
(Index([2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019,
 ...
 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019],
 dtype='int32', name='datetime', length=1033),
 Index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 ...
 3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
 dtype='int32', name='datetime', length=1033)) 

其他一些优点是方便地对时间段进行子集划分或在图表上调整时间刻度。让我们在我们的数据上应用这个方法。

  • 创建从 5 月 20 日到 5 月 21 日结束的不同站点(NO_2)值的图表。

    In [21]: no_2["2019-05-20":"2019-05-21"].plot(); 
    

    ../../_images/09_time_section.png

    通过提供解析为日期时间的字符串,可以在DatetimeIndex上选择特定的数据子集。

到用户指南

更多关于DatetimeIndex和使用字符串进行切片的信息,请参阅时间序列索引部分。

将时间序列重新采样到另一个频率

  • 将当前每小时时间序列值聚合到各站点的每月最大值。

    In [22]: monthly_max = no_2.resample("ME").max()
    
    In [23]: monthly_max
    Out[23]: 
    location                   BETR801  FR04014  London Westminster
    datetime 
    2019-05-31 00:00:00+00:00     74.5     97.0                97.0
    2019-06-30 00:00:00+00:00     52.5     84.7                52.0 
    

    在具有日期时间索引的时间序列数据上非常强大的方法是能够将时间序列resample()到另一个频率(例如,将每秒数据转换为每 5 分钟的数据)。

resample()方法类似于分组操作:

  • 它提供了基于时间的分组,通过使用定义目标频率的字符串(例如M5H等)

  • 它需要一个聚合函数,如meanmax等。

到用户指南

在偏移别名概述表中提供了用于定义时间序列频率的别名的概述。

当定义时,时间序列的频率由freq属性提供:

In [24]: monthly_max.index.freq
Out[24]: <MonthEnd> 
  • 绘制每个站点的每日平均(NO_2)值的图表。

    In [25]: no_2.resample("D").mean().plot(style="-o", figsize=(10, 5)); 
    

    ../../_images/09_resample_mean.png

到用户指南

更多关于时间序列重新采样强大功能的详细信息,请参阅用户指南中的重新采样部分。

记住

  • 有效的日期字符串可以使用to_datetime函数或作为读取函数的一部分转换为日期时间对象。

  • pandas 中的日期时间对象支持使用dt访问器进行计算、逻辑操作和方便的与日期相关的属性。

  • DatetimeIndex 包含这些与日期相关的属性,并支持方便的切片。

  • Resample 是改变时间序列频率的强大方法。

用户指南

有关时间序列的完整概述可在时间序列和日期功能页面上找到。

如何操作文本数据

原文:pandas.pydata.org/docs/getting_started/intro_tutorials/10_text_data.html

  • 将所有名称字符改为小写。

    In [4]: titanic["Name"].str.lower()
    Out[4]: 
    0                                braund, mr. owen harris
    1      cumings, mrs. john bradley (florence briggs th...
    2                                 heikkinen, miss. laina
    3           futrelle, mrs. jacques heath (lily may peel)
    4                               allen, mr. william henry
     ... 
    886                                montvila, rev. juozas
    887                         graham, miss. margaret edith
    888             johnston, miss. catherine helen "carrie"
    889                                behr, mr. karl howell
    890                                  dooley, mr. patrick
    Name: Name, Length: 891, dtype: object 
    

    要使Name列中的每个字符串都变为小写,选择Name列(参见数据选择教程),添加str访问器并应用lower方法。因此,每个字符串都被逐个转换。

与时间序列教程中具有dt访问器的日期时间对象类似,在使用str访问器时可以使用许多专门的字符串方法。这些方法通常与单个元素的内置字符串方法具有匹配的名称,但是在每个值的列上逐个应用(记得逐元素计算吗?)。

  • 创建一个新列Surname,其中包含乘客的姓氏,通过提取逗号前的部分。

    In [5]: titanic["Name"].str.split(",")
    Out[5]: 
    0                             [Braund,  Mr. Owen Harris]
    1      [Cumings,  Mrs. John Bradley (Florence Briggs ...
    2                              [Heikkinen,  Miss. Laina]
    3        [Futrelle,  Mrs. Jacques Heath (Lily May Peel)]
    4                            [Allen,  Mr. William Henry]
     ... 
    886                             [Montvila,  Rev. Juozas]
    887                      [Graham,  Miss. Margaret Edith]
    888          [Johnston,  Miss. Catherine Helen "Carrie"]
    889                             [Behr,  Mr. Karl Howell]
    890                               [Dooley,  Mr. Patrick]
    Name: Name, Length: 891, dtype: object 
    

    使用Series.str.split()方法,每个值都返回一个包含 2 个元素的列表。第一个元素是逗号前的部分,第二个元素是逗号后的部分。

    In [6]: titanic["Surname"] = titanic["Name"].str.split(",").str.get(0)
    
    In [7]: titanic["Surname"]
    Out[7]: 
    0         Braund
    1        Cumings
    2      Heikkinen
    3       Futrelle
    4          Allen
     ... 
    886     Montvila
    887       Graham
    888     Johnston
    889         Behr
    890       Dooley
    Name: Surname, Length: 891, dtype: object 
    

    由于我们只对代表姓氏的第一部分感兴趣(元素 0),我们可以再次使用str访问器,并应用Series.str.get()来提取相关部分。事实上,这些字符串函数可以连接起来组合多个函数!

到用户指南

有关提取字符串部分的更多信息,请参阅用户指南中关于拆分和替换字符串的部分。

  • 提取关于泰坦尼克号上女伯爵的乘客数据。

    In [8]: titanic["Name"].str.contains("Countess")
    Out[8]: 
    0      False
    1      False
    2      False
    3      False
    4      False
     ... 
    886    False
    887    False
    888    False
    889    False
    890    False
    Name: Name, Length: 891, dtype: bool 
    
    In [9]: titanic[titanic["Name"].str.contains("Countess")]
    Out[9]: 
     PassengerId  Survived  Pclass  ... Cabin Embarked  Surname
    759          760         1       1  ...   B77        S   Rothes
    
    [1 rows x 13 columns] 
    

    (对她的故事感兴趣吗?请参阅 维基百科)

    字符串方法Series.str.contains()检查列Name中的每个值是否包含单词Countess,并对每个值返回TrueCountess是名称的一部分)或FalseCountess不是名称的一部分)。此输出可用于使用在数据子集教程中介绍的条件(布尔)索引来对数据进行子选择。由于泰坦尼克号上只有一位女伯爵,我们得到一行作为结果。

注意

字符串的更强大的提取操作是支持的,因为Series.str.contains()Series.str.extract() 方法接受正则表达式,但不在本教程的范围内。

到用户指南

更多有关提取字符串部分的信息,请参阅用户指南中有关字符串匹配和提取的部分。

  • 泰坦尼克号的乘客中,哪位乘客的名字最长?

    In [10]: titanic["Name"].str.len()
    Out[10]: 
    0      23
    1      51
    2      22
    3      44
    4      24
     ..
    886    21
    887    28
    888    40
    889    21
    890    19
    Name: Name, Length: 891, dtype: int64 
    

    要获得最长的名称,我们首先必须获取Name列中每个名称的长度。通过使用 pandas 字符串方法,对每个名称单独应用Series.str.len()函数(逐元素)。

    In [11]: titanic["Name"].str.len().idxmax()
    Out[11]: 307 
    

    接下来,我们需要获取对应位置,最好是表格中名字长度最大的索引标签。 idxmax() 方法正是这样做的。它不是字符串方法,适用于整数,因此不使用str

    In [12]: titanic.loc[titanic["Name"].str.len().idxmax(), "Name"]
    Out[12]: 'Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)' 
    

    基于行的索引名称(307)和列的名称(Name),我们可以使用loc运算符进行选择,该运算符在子集切片教程中介绍过。

  • 在“性别”列中,将“male”的值替换为“M”,将“female”的值替换为“F”。

    In [13]: titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"})
    
    In [14]: titanic["Sex_short"]
    Out[14]: 
    0      M
    1      F
    2      F
    3      F
    4      M
     ..
    886    M
    887    F
    888    F
    889    M
    890    M
    Name: Sex_short, Length: 891, dtype: object 
    

    replace() 不是一个字符串方法,它提供了一种方便的方式来使用映射或词汇表来转换某些值。它需要一个dictionary来定义映射 {from : to}

警告

还有一个可用的replace()方法,可以替换特定的字符集。但是,当有多个值的映射时,这将变得:

titanic["Sex_short"] = titanic["Sex"].str.replace("female", "F")
titanic["Sex_short"] = titanic["Sex_short"].str.replace("male", "M") 

这将变得繁琐,并且很容易出错。想想(或者试试)如果这两个语句以相反的顺序应用会发生什么…

记住

  • 可以使用str访问器使用字符串方法。

  • 字符串方法是逐元素进行的,可以用于条件索引。

  • replace方法是根据给定字典转换值的便捷方法。

到用户指南

用户指南页面提供了处理文本数据的全面概述。

与其他工具的比较

原文:pandas.pydata.org/docs/getting_started/comparison/index.html

  • 与 R / R 库的比较

    • 快速参考

    • 基本 R

    • plyr

    • reshape / reshape2

  • 与 SQL 的比较

    • 复制 vs. 原地操作

    • 选择

    • WHERE

    • GROUP BY

    • 连接

    • UNION

    • 限制

    • pandas 对一些 SQL 分析和聚合函数的等效操作

    • 更新

    • 删除

  • 与电子表格的比较

    • 数据结构

    • 数据输入/输出

    • 数据操作

    • 字符串处理

    • 合并

    • 其他考虑因素

  • 与 SAS 的比较

    • 数据结构

    • 数据输入/输出

    • 数据操作

    • 字符串处理

    • 合并

    • 缺失数据

    • GroupBy

    • 其他考虑因素

  • 与 Stata 的比较

    • 数据结构

    • 数据输入/输出

    • 数据操作

    • 字符串处理

    • 合并

    • 缺失数据

    • GroupBy

    • 其他考虑因素

与 R/R 库的比较

译文:pandas.pydata.org/docs/getting_started/comparison/comparison_with_r.html

由于 pandas 旨在提供许多人们使用R的数据操作和分析功能,因此本页面旨在更详细地查看R 语言及其许多第三方库与 pandas 的关系。在与 R 和 CRAN 库的比较中,我们关心以下几点:

  • 功能性/灵活性:每个工具可以/不可以做什么

  • 性能:操作有多快。最好提供硬性数据/基准

  • 易用性:一个工具更容易/更难使用(您可能需要通过并排代码比较来判断)

本页面还提供了一个为这些 R 包的用户提供一点翻译指南的页面。

快速参考

我们将从一个快速参考指南开始,将一些常见的 R 操作(使用dplyr)与 pandas 的等效操作进行配对。

查询、过滤、抽样

R pandas
dim(df) df.shape
head(df) df.head()
slice(df, 1:10) df.iloc[:9]
filter(df, col1 == 1, col2 == 1) df.query('col1 == 1 & col2 == 1')
df[df$col1 == 1 & df$col2 == 1,] df[(df.col1 == 1) & (df.col2 == 1)]
select(df, col1, col2) df[['col1', 'col2']]
select(df, col1:col3) df.loc[:, 'col1':'col3']
select(df, -(col1:col3)) df.drop(cols_to_drop, axis=1) 但请参见[1]
distinct(select(df, col1)) df[['col1']].drop_duplicates()
distinct(select(df, col1, col2)) df[['col1', 'col2']].drop_duplicates()
sample_n(df, 10) df.sample(n=10)
sample_frac(df, 0.01) df.sample(frac=0.01)

排序

R pandas
arrange(df, col1, col2) df.sort_values(['col1', 'col2'])
arrange(df, desc(col1)) df.sort_values('col1', ascending=False)

转换

R pandas
select(df, col_one = col1) df.rename(columns={'col1': 'col_one'})['col_one']
rename(df, col_one = col1) df.rename(columns={'col1': 'col_one'})
mutate(df, c=a-b) df.assign(c=df['a']-df['b'])

分组和汇总

R pandas
summary(df) df.describe()
gdf <- group_by(df, col1) gdf = df.groupby('col1')
summarise(gdf, avg=mean(col1, na.rm=TRUE)) df.groupby('col1').agg({'col1': 'mean'})
summarise(gdf, total=sum(col1)) df.groupby('col1').sum()

基础 R

使用 R 的c进行切片

R 使得通过名称轻松访问 data.frame 列成为可能

df  <-  data.frame(a=rnorm(5),  b=rnorm(5),  c=rnorm(5),  d=rnorm(5),  e=rnorm(5))
df[,  c("a",  "c",  "e")] 

或按整数位置

df  <-  data.frame(matrix(rnorm(1000),  ncol=100))
df[,  c(1:10,  25:30,  40,  50:100)] 

在 pandas 中按名称选择多列很简单

In [1]: df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc"))

In [2]: df[["a", "c"]]
Out[2]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892

In [3]: df.loc[:, ["a", "c"]]
Out[3]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892 

通过整数位置选择多个不连续列可以通过iloc索引器属性和numpy.r_的组合实现。

In [4]: named = list("abcdefg")

In [5]: n = 30

In [6]: columns = named + np.arange(len(named), n).tolist()

In [7]: df = pd.DataFrame(np.random.randn(n, n), columns=columns)

In [8]: df.iloc[:, np.r_[:10, 24:30]]
Out[8]: 
 a         b         c  ...        27        28        29
0  -1.344312  0.844885  1.075770  ...  0.813850  0.132003 -0.827317
1  -0.076467 -1.187678  1.130127  ...  0.149748 -0.732339  0.687738
2   0.176444  0.403310 -0.154951  ... -0.493662  0.600178  0.274230
3   0.132885 -0.023688  2.410179  ...  0.109121  1.126203 -0.977349
4   1.474071 -0.064034 -1.282782  ... -0.858447  0.306996 -0.028665
..       ...       ...       ...  ...       ...       ...       ...
25  1.492125 -0.068190  0.681456  ...  0.428572  0.880609  0.487645
26  0.725238  0.624607 -0.141185  ...  1.008500  1.424017  0.717110
27  1.262419  1.950057  0.301038  ...  1.007824  2.826008  1.458383
28 -1.585746 -0.899734  0.921494  ...  0.577223 -1.088417  0.326687
29 -0.986248  0.169729 -1.158091  ... -2.013086 -1.602549  0.333109

[30 rows x 16 columns] 

aggregate

在 R 中,您可能希望将数据拆分为子集并为每个子集计算平均值。使用名为df的数据框,并将其拆分为by1by2组:

df  <-  data.frame(
  v1  =  c(1,3,5,7,8,3,5,NA,4,5,7,9),
  v2  =  c(11,33,55,77,88,33,55,NA,44,55,77,99),
  by1  =  c("red",  "blue",  1,  2,  NA,  "big",  1,  2,  "red",  1,  NA,  12),
  by2  =  c("wet",  "dry",  99,  95,  NA,  "damp",  95,  99,  "red",  99,  NA,  NA))
aggregate(x=df[,  c("v1",  "v2")],  by=list(mydf2$by1,  mydf2$by2),  FUN  =  mean) 

groupby()方法类似于基本的 R aggregate函数。

In [9]: df = pd.DataFrame(
 ...:    {
 ...:        "v1": [1, 3, 5, 7, 8, 3, 5, np.nan, 4, 5, 7, 9],
 ...:        "v2": [11, 33, 55, 77, 88, 33, 55, np.nan, 44, 55, 77, 99],
 ...:        "by1": ["red", "blue", 1, 2, np.nan, "big", 1, 2, "red", 1, np.nan, 12],
 ...:        "by2": [
 ...:            "wet",
 ...:            "dry",
 ...:            99,
 ...:            95,
 ...:            np.nan,
 ...:            "damp",
 ...:            95,
 ...:            99,
 ...:            "red",
 ...:            99,
 ...:            np.nan,
 ...:            np.nan,
 ...:        ],
 ...:    }
 ...: )
 ...: 

In [10]: g = df.groupby(["by1", "by2"])

In [11]: g[["v1", "v2"]].mean()
Out[11]: 
 v1    v2
by1  by2 
1    95    5.0  55.0
 99    5.0  55.0
2    95    7.0  77.0
 99    NaN   NaN
big  damp  3.0  33.0
blue dry   3.0  33.0
red  red   4.0  44.0
 wet   1.0  11.0 

有关更多详细信息和示例,请参阅分组文档。

match / %in%

在 R 中选择数据的常见方法是使用%in%,该运算符使用函数match定义。运算符%in%用于返回指示是否存在匹配项的逻辑向量:

s  <-  0:4
s  %in%  c(2,4) 

isin()方法类似于 R 的%in%运算符:

In [12]: s = pd.Series(np.arange(5), dtype=np.float32)

In [13]: s.isin([2, 4])
Out[13]: 
0    False
1    False
2     True
3    False
4     True
dtype: bool 

match函数返回其第一个参数在第二个参数中匹配位置的向量:

s  <-  0:4
match(s,  c(2,4)) 

有关更多详细信息和示例,请参阅重塑文档。

tapply

tapply类似于aggregate,但数据可以是不规则的数组,因为子类大小可能不规则。使用名为baseball的数据框,并根据数组team检索信息:

baseball  <-
  data.frame(team  =  gl(5,  5,
  labels  =  paste("Team",  LETTERS[1:5])),
  player  =  sample(letters,  25),
  batting.average  =  runif(25,  .200,  .400))

tapply(baseball$batting.average,  baseball.example$team,
  max) 

在 pandas 中,我们可以使用pivot_table()方法来处理这个问题:

In [14]: import random

In [15]: import string

In [16]: baseball = pd.DataFrame(
 ....:    {
 ....:        "team": ["team %d" % (x + 1) for x in range(5)] * 5,
 ....:        "player": random.sample(list(string.ascii_lowercase), 25),
 ....:        "batting avg": np.random.uniform(0.200, 0.400, 25),
 ....:    }
 ....: )
 ....: 

In [17]: baseball.pivot_table(values="batting avg", columns="team", aggfunc="max")
Out[17]: 
team           team 1    team 2    team 3    team 4    team 5
batting avg  0.352134  0.295327  0.397191  0.394457  0.396194 

有关更多详细信息和示例,请参阅重塑文档。

subset

query()方法类似于基本的 R subset函数。在 R 中,您可能希望获取data.frame的行,其中一列的值小于另一列的值:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
subset(df,  a  <=  b)
df[df$a  <=  df$b,]  # note the comma 

在 pandas 中,有几种方法可以执行子集。您可以使用query()或将表达式传递为索引/切片,以及标准布尔索引:

In [18]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [19]: df.query("a <= b")
Out[19]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [20]: df[df["a"] <= df["b"]]
Out[20]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [21]: df.loc[df["a"] <= df["b"]]
Out[21]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550 

有关更多详细信息和示例,请参阅查询文档。

with

在 R 中使用名为df的数据框,其中包含ab列的表达式将使用with进行评估:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
with(df,  a  +  b)
df$a  +  df$b  # same as the previous expression 

在 pandas 中,使用eval()方法的等效表达式将是:

In [22]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [23]: df.eval("a + b")
Out[23]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64

In [24]: df["a"] + df["b"]  # same as the previous expression
Out[24]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64 

在某些情况下,eval() 比纯 Python 中的评估要快得多。更多详细信息和示例请参见 eval 文档。

plyr

plyr 是一个用于数据分析的 R 库,围绕着 R 中的三种数据结构 a(数组)、l(列表)和 d(数据框)展开。下表显示了这些数据结构在 Python 中的映射方式。

R Python
数组 列表
列表 字典或对象列表
data.frame 数据框

ddply

在 R 中使用名为 df 的 data.frame 来按 month 汇总 x 的表达式:

require(plyr)
df  <-  data.frame(
  x  =  runif(120,  1,  168),
  y  =  runif(120,  7,  334),
  z  =  runif(120,  1.7,  20.7),
  month  =  rep(c(5,6,7,8),30),
  week  =  sample(1:4,  120,  TRUE)
)

ddply(df,  .(month,  week),  summarize,
  mean  =  round(mean(x),  2),
  sd  =  round(sd(x),  2)) 

在 pandas 中,等效的表达式,使用 groupby() 方法,将是:

In [25]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 120),
 ....:        "y": np.random.uniform(7.0, 334.0, 120),
 ....:        "z": np.random.uniform(1.7, 20.7, 120),
 ....:        "month": [5, 6, 7, 8] * 30,
 ....:        "week": np.random.randint(1, 4, 120),
 ....:    }
 ....: )
 ....: 

In [26]: grouped = df.groupby(["month", "week"])

In [27]: grouped["x"].agg(["mean", "std"])
Out[27]: 
 mean        std
month week 
5     1      63.653367  40.601965
 2      78.126605  53.342400
 3      92.091886  57.630110
6     1      81.747070  54.339218
 2      70.971205  54.687287
 3     100.968344  54.010081
7     1      61.576332  38.844274
 2      61.733510  48.209013
 3      71.688795  37.595638
8     1      62.741922  34.618153
 2      91.774627  49.790202
 3      73.936856  60.773900 

更多详细信息和示例请参见 分组文档。

reshape / reshape2

meltarray

在 R 中使用名为 a 的 3 维数组来将其融合成一个 data.frame 的表达式:

a  <-  array(c(1:23,  NA),  c(2,3,4))
data.frame(melt(a)) 

在 Python 中,由于 a 是一个列表,你可以简单地使用列表推导式。

In [28]: a = np.array(list(range(1, 24)) + [np.NAN]).reshape(2, 3, 4)

In [29]: pd.DataFrame([tuple(list(x) + [val]) for x, val in np.ndenumerate(a)])
Out[29]: 
 0  1  2     3
0   0  0  0   1.0
1   0  0  1   2.0
2   0  0  2   3.0
3   0  0  3   4.0
4   0  1  0   5.0
.. .. .. ..   ...
19  1  1  3  20.0
20  1  2  0  21.0
21  1  2  1  22.0
22  1  2  2  23.0
23  1  2  3   NaN

[24 rows x 4 columns] 

meltlist

在 R 中使用名为 a 的列表来将其融合成一个 data.frame 的表达式:

a  <-  as.list(c(1:4,  NA))
data.frame(melt(a)) 

在 Python 中,这个列表将是一个元组的列表,因此 DataFrame() 方法将其转换为所需的数据框。

In [30]: a = list(enumerate(list(range(1, 5)) + [np.NAN]))

In [31]: pd.DataFrame(a)
Out[31]: 
 0    1
0  0  1.0
1  1  2.0
2  2  3.0
3  3  4.0
4  4  NaN 

更多详细信息和示例请参见 数据结构入门文档。

meltdf

在 R 中使用名为 cheese 的 data.frame 来重新塑造数据框的表达式:

cheese  <-  data.frame(
  first  =  c('John',  'Mary'),
  last  =  c('Doe',  'Bo'),
  height  =  c(5.5,  6.0),
  weight  =  c(130,  150)
)
melt(cheese,  id=c("first",  "last")) 

在 Python 中,melt() 方法是 R 中的等效方法:

In [32]: cheese = pd.DataFrame(
 ....:    {
 ....:        "first": ["John", "Mary"],
 ....:        "last": ["Doe", "Bo"],
 ....:        "height": [5.5, 6.0],
 ....:        "weight": [130, 150],
 ....:    }
 ....: )
 ....: 

In [33]: pd.melt(cheese, id_vars=["first", "last"])
Out[33]: 
 first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0

In [34]: cheese.set_index(["first", "last"]).stack(future_stack=True)  # alternative way
Out[34]: 
first  last 
John   Doe   height      5.5
 weight    130.0
Mary   Bo    height      6.0
 weight    150.0
dtype: float64 

更多详细信息和示例请参见 重塑文档。

cast

在 R 中,acast 是使用名为 df 的 data.frame 来转换为更高维数组的表达式:

df  <-  data.frame(
  x  =  runif(12,  1,  168),
  y  =  runif(12,  7,  334),
  z  =  runif(12,  1.7,  20.7),
  month  =  rep(c(5,6,7),4),
  week  =  rep(c(1,2),  6)
)

mdf  <-  melt(df,  id=c("month",  "week"))
acast(mdf,  week  ~  month  ~  variable,  mean) 

在 Python 中,最好的方法是利用 pivot_table()

In [35]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 12),
 ....:        "y": np.random.uniform(7.0, 334.0, 12),
 ....:        "z": np.random.uniform(1.7, 20.7, 12),
 ....:        "month": [5, 6, 7] * 4,
 ....:        "week": [1, 2] * 6,
 ....:    }
 ....: )
 ....: 

In [36]: mdf = pd.melt(df, id_vars=["month", "week"])

In [37]: pd.pivot_table(
 ....:    mdf,
 ....:    values="value",
 ....:    index=["variable", "week"],
 ....:    columns=["month"],
 ....:    aggfunc="mean",
 ....: )
 ....: 
Out[37]: 
month                  5           6           7
variable week 
x        1     93.888747   98.762034   55.219673
 2     94.391427   38.112932   83.942781
y        1     94.306912  279.454811  227.840449
 2     87.392662  193.028166  173.899260
z        1     11.016009   10.079307   16.170549
 2      8.476111   17.638509   19.003494 

类似于在 R 中使用名为 df 的 data.frame 来基于 AnimalFeedType 聚合信息的 dcast

df  <-  data.frame(
  Animal  =  c('Animal1',  'Animal2',  'Animal3',  'Animal2',  'Animal1',
  'Animal2',  'Animal3'),
  FeedType  =  c('A',  'B',  'A',  'A',  'B',  'B',  'A'),
  Amount  =  c(10,  7,  4,  2,  5,  6,  2)
)

dcast(df,  Animal  ~  FeedType,  sum,  fill=NaN)
# Alternative method using base R
with(df,  tapply(Amount,  list(Animal,  FeedType),  sum)) 

Python 可以通过两种不同的方式来处理这个问题。首先,类似于上面使用 pivot_table()

In [38]: df = pd.DataFrame(
 ....:    {
 ....:        "Animal": [
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:            "Animal2",
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:        ],
 ....:        "FeedType": ["A", "B", "A", "A", "B", "B", "A"],
 ....:        "Amount": [10, 7, 4, 2, 5, 6, 2],
 ....:    }
 ....: )
 ....: 

In [39]: df.pivot_table(values="Amount", index="Animal", columns="FeedType", aggfunc="sum")
Out[39]: 
FeedType     A     B
Animal 
Animal1   10.0   5.0
Animal2    2.0  13.0
Animal3    6.0   NaN 

第二种方法是使用 groupby() 方法:

In [40]: df.groupby(["Animal", "FeedType"])["Amount"].sum()
Out[40]: 
Animal   FeedType
Animal1  A           10
 B            5
Animal2  A            2
 B           13
Animal3  A            6
Name: Amount, dtype: int64 

更多详细信息和示例请参见 重塑文档 或 分组文档。

factor

pandas 有一种用于分类数据的数据类型。

cut(c(1,2,3,4,5,6),  3)
factor(c(1,2,3,2,2,3)) 

在 pandas 中可以用 pd.cutastype("category") 实现:

In [41]: pd.cut(pd.Series([1, 2, 3, 4, 5, 6]), 3)
Out[41]: 
0    (0.995, 2.667]
1    (0.995, 2.667]
2    (2.667, 4.333]
3    (2.667, 4.333]
4      (4.333, 6.0]
5      (4.333, 6.0]
dtype: category
Categories (3, interval[float64, right]): [(0.995, 2.667] < (2.667, 4.333] < (4.333, 6.0]]

In [42]: pd.Series([1, 2, 3, 2, 2, 3]).astype("category")
Out[42]: 
0    1
1    2
2    3
3    2
4    2
5    3
dtype: category
Categories (3, int64): [1, 2, 3] 

更多详情和示例请参阅 分类简介 和 API 文档。还有关于 与 R 的因子的区别 的文档。

快速参考

我们将从一个快速参考指南开始,将一些常见的 R 操作(使用 dplyr)与 pandas 的等价操作进行对比。

查询、过滤、抽样

R pandas
dim(df) df.shape
head(df) df.head()
slice(df, 1:10) df.iloc[:9]
filter(df, col1 == 1, col2 == 1) df.query('col1 == 1 & col2 == 1')
df[df$col1 == 1 & df$col2 == 1,] df[(df.col1 == 1) & (df.col2 == 1)]
select(df, col1, col2) df[['col1', 'col2']]
select(df, col1:col3) df.loc[:, 'col1':'col3']
select(df, -(col1:col3)) df.drop(cols_to_drop, axis=1) 但见 [1]
distinct(select(df, col1)) df[['col1']].drop_duplicates()
distinct(select(df, col1, col2)) df[['col1', 'col2']].drop_duplicates()
sample_n(df, 10) df.sample(n=10)
sample_frac(df, 0.01) df.sample(frac=0.01)

排序

R pandas
arrange(df, col1, col2) df.sort_values(['col1', 'col2'])
arrange(df, desc(col1)) df.sort_values('col1', ascending=False)

转换

R pandas
select(df, col_one = col1) df.rename(columns={'col1': 'col_one'})['col_one']
rename(df, col_one = col1) df.rename(columns={'col1': 'col_one'})
mutate(df, c=a-b) df.assign(c=df['a']-df['b'])

分组和汇总

R pandas
summary(df) df.describe()
gdf <- group_by(df, col1) gdf = df.groupby('col1')
summarise(gdf, avg=mean(col1, na.rm=TRUE)) df.groupby('col1').agg({'col1': 'mean'})
summarise(gdf, total=sum(col1)) df.groupby('col1').sum()

查询、过滤、抽样

R pandas
dim(df) df.shape
head(df) df.head()
slice(df, 1:10) df.iloc[:9]
filter(df, col1 == 1, col2 == 1) df.query('col1 == 1 & col2 == 1')
df[df$col1 == 1 & df$col2 == 1,] df[(df.col1 == 1) & (df.col2 == 1)]
select(df, col1, col2) df[['col1', 'col2']]
select(df, col1:col3) df.loc[:, 'col1':'col3']
select(df, -(col1:col3)) df.drop(cols_to_drop, axis=1) 但见 [1]
distinct(select(df, col1)) df[['col1']].drop_duplicates()
distinct(select(df, col1, col2)) df[['col1', 'col2']].drop_duplicates()
sample_n(df, 10) df.sample(n=10)
sample_frac(df, 0.01) df.sample(frac=0.01)

排序

R pandas
arrange(df, col1, col2) df.sort_values(['col1', 'col2'])
arrange(df, desc(col1)) df.sort_values('col1', ascending=False)

转换

R pandas
select(df, col_one = col1) df.rename(columns={'col1': 'col_one'})['col_one']
rename(df, col_one = col1) df.rename(columns={'col1': 'col_one'})
mutate(df, c=a-b) df.assign(c=df['a']-df['b'])

分组和汇总

R pandas
summary(df) df.describe()
gdf <- group_by(df, col1) gdf = df.groupby('col1')
summarise(gdf, avg=mean(col1, na.rm=TRUE)) df.groupby('col1').agg({'col1': 'mean'})
summarise(gdf, total=sum(col1)) df.groupby('col1').sum()

基本 R

使用 R 的 c 进行切片

R 使得通过名称轻松访问 data.frame

df  <-  data.frame(a=rnorm(5),  b=rnorm(5),  c=rnorm(5),  d=rnorm(5),  e=rnorm(5))
df[,  c("a",  "c",  "e")] 

或通过整数位置

df  <-  data.frame(matrix(rnorm(1000),  ncol=100))
df[,  c(1:10,  25:30,  40,  50:100)] 

在 pandas 中通过名称选择多列很简单

In [1]: df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc"))

In [2]: df[["a", "c"]]
Out[2]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892

In [3]: df.loc[:, ["a", "c"]]
Out[3]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892 

通过整数位置选择多个不连续的列可以通过 iloc 索引器属性和 numpy.r_ 的组合实现。

In [4]: named = list("abcdefg")

In [5]: n = 30

In [6]: columns = named + np.arange(len(named), n).tolist()

In [7]: df = pd.DataFrame(np.random.randn(n, n), columns=columns)

In [8]: df.iloc[:, np.r_[:10, 24:30]]
Out[8]: 
 a         b         c  ...        27        28        29
0  -1.344312  0.844885  1.075770  ...  0.813850  0.132003 -0.827317
1  -0.076467 -1.187678  1.130127  ...  0.149748 -0.732339  0.687738
2   0.176444  0.403310 -0.154951  ... -0.493662  0.600178  0.274230
3   0.132885 -0.023688  2.410179  ...  0.109121  1.126203 -0.977349
4   1.474071 -0.064034 -1.282782  ... -0.858447  0.306996 -0.028665
..       ...       ...       ...  ...       ...       ...       ...
25  1.492125 -0.068190  0.681456  ...  0.428572  0.880609  0.487645
26  0.725238  0.624607 -0.141185  ...  1.008500  1.424017  0.717110
27  1.262419  1.950057  0.301038  ...  1.007824  2.826008  1.458383
28 -1.585746 -0.899734  0.921494  ...  0.577223 -1.088417  0.326687
29 -0.986248  0.169729 -1.158091  ... -2.013086 -1.602549  0.333109

[30 rows x 16 columns] 

aggregate

在 R 中,您可能希望将数据拆分为子集,并为每个子集计算平均值。使用名为 df 的数据框,并将其拆分为 by1by2 组:

df  <-  data.frame(
  v1  =  c(1,3,5,7,8,3,5,NA,4,5,7,9),
  v2  =  c(11,33,55,77,88,33,55,NA,44,55,77,99),
  by1  =  c("red",  "blue",  1,  2,  NA,  "big",  1,  2,  "red",  1,  NA,  12),
  by2  =  c("wet",  "dry",  99,  95,  NA,  "damp",  95,  99,  "red",  99,  NA,  NA))
aggregate(x=df[,  c("v1",  "v2")],  by=list(mydf2$by1,  mydf2$by2),  FUN  =  mean) 

groupby() 方法类似于基本的 R aggregate 函数。

In [9]: df = pd.DataFrame(
 ...:    {
 ...:        "v1": [1, 3, 5, 7, 8, 3, 5, np.nan, 4, 5, 7, 9],
 ...:        "v2": [11, 33, 55, 77, 88, 33, 55, np.nan, 44, 55, 77, 99],
 ...:        "by1": ["red", "blue", 1, 2, np.nan, "big", 1, 2, "red", 1, np.nan, 12],
 ...:        "by2": [
 ...:            "wet",
 ...:            "dry",
 ...:            99,
 ...:            95,
 ...:            np.nan,
 ...:            "damp",
 ...:            95,
 ...:            99,
 ...:            "red",
 ...:            99,
 ...:            np.nan,
 ...:            np.nan,
 ...:        ],
 ...:    }
 ...: )
 ...: 

In [10]: g = df.groupby(["by1", "by2"])

In [11]: g[["v1", "v2"]].mean()
Out[11]: 
 v1    v2
by1  by2 
1    95    5.0  55.0
 99    5.0  55.0
2    95    7.0  77.0
 99    NaN   NaN
big  damp  3.0  33.0
blue dry   3.0  33.0
red  red   4.0  44.0
 wet   1.0  11.0 

有关更多详细信息和示例,请参阅分组文档。

match / %in%

%in% 在 R 中选择数据的常见方法是使用 match 函数定义的。操作符 %in% 用于返回一个逻辑向量,指示是否有匹配项:

s  <-  0:4
s  %in%  c(2,4) 

isin() 方法类似于 R 的 %in% 操作符:

In [12]: s = pd.Series(np.arange(5), dtype=np.float32)

In [13]: s.isin([2, 4])
Out[13]: 
0    False
1    False
2     True
3    False
4     True
dtype: bool 

match 函数返回其第一个参数在第二个参数中的匹配位置的向量:

s  <-  0:4
match(s,  c(2,4)) 

有关更多详细信息和示例,请参阅重塑文档。

tapply

tapply 类似于 aggregate,但数据可以是不规则的,因为子类大小可能不规则。使用名为 baseball 的数据框,并根据数组 team 检索信息:

baseball  <-
  data.frame(team  =  gl(5,  5,
  labels  =  paste("Team",  LETTERS[1:5])),
  player  =  sample(letters,  25),
  batting.average  =  runif(25,  .200,  .400))

tapply(baseball$batting.average,  baseball.example$team,
  max) 

在 pandas 中,我们可以使用 pivot_table() 方法来处理这个问题:

In [14]: import random

In [15]: import string

In [16]: baseball = pd.DataFrame(
 ....:    {
 ....:        "team": ["team %d" % (x + 1) for x in range(5)] * 5,
 ....:        "player": random.sample(list(string.ascii_lowercase), 25),
 ....:        "batting avg": np.random.uniform(0.200, 0.400, 25),
 ....:    }
 ....: )
 ....: 

In [17]: baseball.pivot_table(values="batting avg", columns="team", aggfunc="max")
Out[17]: 
team           team 1    team 2    team 3    team 4    team 5
batting avg  0.352134  0.295327  0.397191  0.394457  0.396194 

有关更多详细信息和示例,请参阅重塑文档。

subset

query()方法类似于基本的 R subset 函数。在 R 中,您可能希望获取data.frame的行,其中一列的值小于另一列的值:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
subset(df,  a  <=  b)
df[df$a  <=  df$b,]  # note the comma 

在 pandas 中,有几种执行子集的方法。您可以使用query()或将表达式传递为索引/切片,以及标准布尔索引:

In [18]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [19]: df.query("a <= b")
Out[19]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [20]: df[df["a"] <= df["b"]]
Out[20]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [21]: df.loc[df["a"] <= df["b"]]
Out[21]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550 

更多详细信息和示例请参见查询文档。

with

在 R 中使用名为df的数据框(data.frame)和列ab的表达式将使用with进行评估,如下所示:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
with(df,  a  +  b)
df$a  +  df$b  # same as the previous expression 

在 pandas 中,使用eval()方法的等价表达式将是:

In [22]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [23]: df.eval("a + b")
Out[23]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64

In [24]: df["a"] + df["b"]  # same as the previous expression
Out[24]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64 

在某些情况下,eval()比纯 Python 中的评估要快得多。更多详细信息和示例请参见评估文档。

使用 R 的c进行切片

R 可以轻松通过名称访问data.frame

df  <-  data.frame(a=rnorm(5),  b=rnorm(5),  c=rnorm(5),  d=rnorm(5),  e=rnorm(5))
df[,  c("a",  "c",  "e")] 

或通过整数位置

df  <-  data.frame(matrix(rnorm(1000),  ncol=100))
df[,  c(1:10,  25:30,  40,  50:100)] 

在 pandas 中按名称选择多个列非常简单

In [1]: df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc"))

In [2]: df[["a", "c"]]
Out[2]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892

In [3]: df.loc[:, ["a", "c"]]
Out[3]: 
 a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892 

通过iloc索引器属性和numpy.r_的组合可以实现通过整数位置选择多个非连续列。

In [4]: named = list("abcdefg")

In [5]: n = 30

In [6]: columns = named + np.arange(len(named), n).tolist()

In [7]: df = pd.DataFrame(np.random.randn(n, n), columns=columns)

In [8]: df.iloc[:, np.r_[:10, 24:30]]
Out[8]: 
 a         b         c  ...        27        28        29
0  -1.344312  0.844885  1.075770  ...  0.813850  0.132003 -0.827317
1  -0.076467 -1.187678  1.130127  ...  0.149748 -0.732339  0.687738
2   0.176444  0.403310 -0.154951  ... -0.493662  0.600178  0.274230
3   0.132885 -0.023688  2.410179  ...  0.109121  1.126203 -0.977349
4   1.474071 -0.064034 -1.282782  ... -0.858447  0.306996 -0.028665
..       ...       ...       ...  ...       ...       ...       ...
25  1.492125 -0.068190  0.681456  ...  0.428572  0.880609  0.487645
26  0.725238  0.624607 -0.141185  ...  1.008500  1.424017  0.717110
27  1.262419  1.950057  0.301038  ...  1.007824  2.826008  1.458383
28 -1.585746 -0.899734  0.921494  ...  0.577223 -1.088417  0.326687
29 -0.986248  0.169729 -1.158091  ... -2.013086 -1.602549  0.333109

[30 rows x 16 columns] 

aggregate

在 R 中,您可能希望将数据拆分为子集并为每个子集计算平均值。使用名为df的数据框,并将其拆分为组by1by2

df  <-  data.frame(
  v1  =  c(1,3,5,7,8,3,5,NA,4,5,7,9),
  v2  =  c(11,33,55,77,88,33,55,NA,44,55,77,99),
  by1  =  c("red",  "blue",  1,  2,  NA,  "big",  1,  2,  "red",  1,  NA,  12),
  by2  =  c("wet",  "dry",  99,  95,  NA,  "damp",  95,  99,  "red",  99,  NA,  NA))
aggregate(x=df[,  c("v1",  "v2")],  by=list(mydf2$by1,  mydf2$by2),  FUN  =  mean) 

groupby()方法类似于基本的 R aggregate 函数。

In [9]: df = pd.DataFrame(
 ...:    {
 ...:        "v1": [1, 3, 5, 7, 8, 3, 5, np.nan, 4, 5, 7, 9],
 ...:        "v2": [11, 33, 55, 77, 88, 33, 55, np.nan, 44, 55, 77, 99],
 ...:        "by1": ["red", "blue", 1, 2, np.nan, "big", 1, 2, "red", 1, np.nan, 12],
 ...:        "by2": [
 ...:            "wet",
 ...:            "dry",
 ...:            99,
 ...:            95,
 ...:            np.nan,
 ...:            "damp",
 ...:            95,
 ...:            99,
 ...:            "red",
 ...:            99,
 ...:            np.nan,
 ...:            np.nan,
 ...:        ],
 ...:    }
 ...: )
 ...: 

In [10]: g = df.groupby(["by1", "by2"])

In [11]: g[["v1", "v2"]].mean()
Out[11]: 
 v1    v2
by1  by2 
1    95    5.0  55.0
 99    5.0  55.0
2    95    7.0  77.0
 99    NaN   NaN
big  damp  3.0  33.0
blue dry   3.0  33.0
red  red   4.0  44.0
 wet   1.0  11.0 

更多详细信息和示例请参见分组文档。

match / %in%

在 R 中选择数据的常见方式是使用%in%,该运算符使用match函数定义。运算符%in%用于返回一个逻辑向量,指示是否存在匹配项:

s  <-  0:4
s  %in%  c(2,4) 

isin()方法类似于 R 的%in%运算符:

In [12]: s = pd.Series(np.arange(5), dtype=np.float32)

In [13]: s.isin([2, 4])
Out[13]: 
0    False
1    False
2     True
3    False
4     True
dtype: bool 

match函数返回其第一个参数在第二个参数中匹配位置的向量:

s  <-  0:4
match(s,  c(2,4)) 

更多详细信息和示例请参见重塑文档。

tapply

tapply 类似于 aggregate,但数据可以是不规则的数组,因为子类大小可能不规则。使用名为 baseball 的 data.frame,并根据数组 team 检索信息:

baseball  <-
  data.frame(team  =  gl(5,  5,
  labels  =  paste("Team",  LETTERS[1:5])),
  player  =  sample(letters,  25),
  batting.average  =  runif(25,  .200,  .400))

tapply(baseball$batting.average,  baseball.example$team,
  max) 

在 pandas 中,我们可以使用pivot_table()方法来处理这个问题:

In [14]: import random

In [15]: import string

In [16]: baseball = pd.DataFrame(
 ....:    {
 ....:        "team": ["team %d" % (x + 1) for x in range(5)] * 5,
 ....:        "player": random.sample(list(string.ascii_lowercase), 25),
 ....:        "batting avg": np.random.uniform(0.200, 0.400, 25),
 ....:    }
 ....: )
 ....: 

In [17]: baseball.pivot_table(values="batting avg", columns="team", aggfunc="max")
Out[17]: 
team           team 1    team 2    team 3    team 4    team 5
batting avg  0.352134  0.295327  0.397191  0.394457  0.396194 

更多详细信息和示例请参见重塑文档。

subset

query()方法类似于基本的 R subset 函数。在 R 中,您可能希望获取 data.frame 的行,其中一个列的值小于另一个列的值:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
subset(df,  a  <=  b)
df[df$a  <=  df$b,]  # note the comma 

在 pandas 中,有几种方法可以执行子集。您可以使用query()或将表达式传递为索引/切片,以及标准布尔索引:

In [18]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [19]: df.query("a <= b")
Out[19]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [20]: df[df["a"] <= df["b"]]
Out[20]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [21]: df.loc[df["a"] <= df["b"]]
Out[21]: 
 a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550 

更多详细信息和示例请参见查询文档。

with

在 R 中使用名为 df 的 data.frame,具有列 ab,将使用 with 进行评估,如下所示:

df  <-  data.frame(a=rnorm(10),  b=rnorm(10))
with(df,  a  +  b)
df$a  +  df$b  # same as the previous expression 

在 pandas 中,等效的��达式,使用eval()方法,将是:

In [22]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [23]: df.eval("a + b")
Out[23]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64

In [24]: df["a"] + df["b"]  # same as the previous expression
Out[24]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64 

在某些情况下,eval()比纯 Python 中的评估要快得多。更多详细信息和示例请参见 eval 文档。

plyr

plyr 是用于数据分析的分割-应用-组合策略的 R 库。这些函数围绕 R 中的三种数据结构展开,a 代表 arraysl 代表 listsd 代表 data.frame。下表显示了这些数据结构在 Python 中的映射方式。

R Python
array list
lists 字典或对象列表
data.frame dataframe

ddply

在 R 中使用名为 df 的 data.frame 表达式,您想要按 month 汇总 x

require(plyr)
df  <-  data.frame(
  x  =  runif(120,  1,  168),
  y  =  runif(120,  7,  334),
  z  =  runif(120,  1.7,  20.7),
  month  =  rep(c(5,6,7,8),30),
  week  =  sample(1:4,  120,  TRUE)
)

ddply(df,  .(month,  week),  summarize,
  mean  =  round(mean(x),  2),
  sd  =  round(sd(x),  2)) 

在 pandas 中,等效的表达式,使用groupby()方法,将是:

In [25]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 120),
 ....:        "y": np.random.uniform(7.0, 334.0, 120),
 ....:        "z": np.random.uniform(1.7, 20.7, 120),
 ....:        "month": [5, 6, 7, 8] * 30,
 ....:        "week": np.random.randint(1, 4, 120),
 ....:    }
 ....: )
 ....: 

In [26]: grouped = df.groupby(["month", "week"])

In [27]: grouped["x"].agg(["mean", "std"])
Out[27]: 
 mean        std
month week 
5     1      63.653367  40.601965
 2      78.126605  53.342400
 3      92.091886  57.630110
6     1      81.747070  54.339218
 2      70.971205  54.687287
 3     100.968344  54.010081
7     1      61.576332  38.844274
 2      61.733510  48.209013
 3      71.688795  37.595638
8     1      62.741922  34.618153
 2      91.774627  49.790202
 3      73.936856  60.773900 

更多详细信息和示例请参见分组文档。

ddply

在 R 中使用名为 df 的 data.frame 表达式,您想要按 month 汇总 x

require(plyr)
df  <-  data.frame(
  x  =  runif(120,  1,  168),
  y  =  runif(120,  7,  334),
  z  =  runif(120,  1.7,  20.7),
  month  =  rep(c(5,6,7,8),30),
  week  =  sample(1:4,  120,  TRUE)
)

ddply(df,  .(month,  week),  summarize,
  mean  =  round(mean(x),  2),
  sd  =  round(sd(x),  2)) 

在 pandas 中,等效的表达式,使用groupby()方法,将是:

In [25]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 120),
 ....:        "y": np.random.uniform(7.0, 334.0, 120),
 ....:        "z": np.random.uniform(1.7, 20.7, 120),
 ....:        "month": [5, 6, 7, 8] * 30,
 ....:        "week": np.random.randint(1, 4, 120),
 ....:    }
 ....: )
 ....: 

In [26]: grouped = df.groupby(["month", "week"])

In [27]: grouped["x"].agg(["mean", "std"])
Out[27]: 
 mean        std
month week 
5     1      63.653367  40.601965
 2      78.126605  53.342400
 3      92.091886  57.630110
6     1      81.747070  54.339218
 2      70.971205  54.687287
 3     100.968344  54.010081
7     1      61.576332  38.844274
 2      61.733510  48.209013
 3      71.688795  37.595638
8     1      62.741922  34.618153
 2      91.774627  49.790202
 3      73.936856  60.773900 

更多细节和示例请参见分组文档。

reshape / reshape2

meltarray

在 R 中使用名为a的三维数组的表达式,你想要将其融化成数据框:

a  <-  array(c(1:23,  NA),  c(2,3,4))
data.frame(melt(a)) 

在 Python 中,由于a是一个列表,你可以简单地使用列表推导式。

In [28]: a = np.array(list(range(1, 24)) + [np.NAN]).reshape(2, 3, 4)

In [29]: pd.DataFrame([tuple(list(x) + [val]) for x, val in np.ndenumerate(a)])
Out[29]: 
 0  1  2     3
0   0  0  0   1.0
1   0  0  1   2.0
2   0  0  2   3.0
3   0  0  3   4.0
4   0  1  0   5.0
.. .. .. ..   ...
19  1  1  3  20.0
20  1  2  0  21.0
21  1  2  1  22.0
22  1  2  2  23.0
23  1  2  3   NaN

[24 rows x 4 columns] 

meltlist

在 R 中使用名为a的列表的表达式,你想要将其融化成数据框:

a  <-  as.list(c(1:4,  NA))
data.frame(melt(a)) 

在 Python 中,这个列表将是一个元组的列表,所以DataFrame()方法会将其转换为所需的数据框。

In [30]: a = list(enumerate(list(range(1, 5)) + [np.NAN]))

In [31]: pd.DataFrame(a)
Out[31]: 
 0    1
0  0  1.0
1  1  2.0
2  2  3.0
3  3  4.0
4  4  NaN 

更多细节和示例请参见数据结构介绍文档。

meltdf

在 R 中使用名为cheese的数据框的表达式,你想要重塑数据框:

cheese  <-  data.frame(
  first  =  c('John',  'Mary'),
  last  =  c('Doe',  'Bo'),
  height  =  c(5.5,  6.0),
  weight  =  c(130,  150)
)
melt(cheese,  id=c("first",  "last")) 

在 Python 中,melt()方法是 R 的等价物:

In [32]: cheese = pd.DataFrame(
 ....:    {
 ....:        "first": ["John", "Mary"],
 ....:        "last": ["Doe", "Bo"],
 ....:        "height": [5.5, 6.0],
 ....:        "weight": [130, 150],
 ....:    }
 ....: )
 ....: 

In [33]: pd.melt(cheese, id_vars=["first", "last"])
Out[33]: 
 first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0

In [34]: cheese.set_index(["first", "last"]).stack(future_stack=True)  # alternative way
Out[34]: 
first  last 
John   Doe   height      5.5
 weight    130.0
Mary   Bo    height      6.0
 weight    150.0
dtype: float64 

更多细节和示��请参见重塑文档。

转换

在 R 中,acast是一个使用名为df的数据框来转换为更高维数组的表达式:

df  <-  data.frame(
  x  =  runif(12,  1,  168),
  y  =  runif(12,  7,  334),
  z  =  runif(12,  1.7,  20.7),
  month  =  rep(c(5,6,7),4),
  week  =  rep(c(1,2),  6)
)

mdf  <-  melt(df,  id=c("month",  "week"))
acast(mdf,  week  ~  month  ~  variable,  mean) 

在 Python 中,最好的方法是利用pivot_table()

In [35]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 12),
 ....:        "y": np.random.uniform(7.0, 334.0, 12),
 ....:        "z": np.random.uniform(1.7, 20.7, 12),
 ....:        "month": [5, 6, 7] * 4,
 ....:        "week": [1, 2] * 6,
 ....:    }
 ....: )
 ....: 

In [36]: mdf = pd.melt(df, id_vars=["month", "week"])

In [37]: pd.pivot_table(
 ....:    mdf,
 ....:    values="value",
 ....:    index=["variable", "week"],
 ....:    columns=["month"],
 ....:    aggfunc="mean",
 ....: )
 ....: 
Out[37]: 
month                  5           6           7
variable week 
x        1     93.888747   98.762034   55.219673
 2     94.391427   38.112932   83.942781
y        1     94.306912  279.454811  227.840449
 2     87.392662  193.028166  173.899260
z        1     11.016009   10.079307   16.170549
 2      8.476111   17.638509   19.003494 

类似于dcast,它使用在 R 中名为df的数据框来根据AnimalFeedType聚合信息的表达式:

df  <-  data.frame(
  Animal  =  c('Animal1',  'Animal2',  'Animal3',  'Animal2',  'Animal1',
  'Animal2',  'Animal3'),
  FeedType  =  c('A',  'B',  'A',  'A',  'B',  'B',  'A'),
  Amount  =  c(10,  7,  4,  2,  5,  6,  2)
)

dcast(df,  Animal  ~  FeedType,  sum,  fill=NaN)
# Alternative method using base R
with(df,  tapply(Amount,  list(Animal,  FeedType),  sum)) 

Python 可以用两种不同的方式来处理这个问题。首先,类似于上面使用pivot_table()

In [38]: df = pd.DataFrame(
 ....:    {
 ....:        "Animal": [
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:            "Animal2",
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:        ],
 ....:        "FeedType": ["A", "B", "A", "A", "B", "B", "A"],
 ....:        "Amount": [10, 7, 4, 2, 5, 6, 2],
 ....:    }
 ....: )
 ....: 

In [39]: df.pivot_table(values="Amount", index="Animal", columns="FeedType", aggfunc="sum")
Out[39]: 
FeedType     A     B
Animal 
Animal1   10.0   5.0
Animal2    2.0  13.0
Animal3    6.0   NaN 

第二种方法是使用groupby()方法:

In [40]: df.groupby(["Animal", "FeedType"])["Amount"].sum()
Out[40]: 
Animal   FeedType
Animal1  A           10
 B            5
Animal2  A            2
 B           13
Animal3  A            6
Name: Amount, dtype: int64 

更多细节和示例请参见重塑文档或分组文档。

factor

pandas 有一个用于分类数据的数据类型。

cut(c(1,2,3,4,5,6),  3)
factor(c(1,2,3,2,2,3)) 

在 pandas 中,可以通过pd.cutastype("category")来实现:

In [41]: pd.cut(pd.Series([1, 2, 3, 4, 5, 6]), 3)
Out[41]: 
0    (0.995, 2.667]
1    (0.995, 2.667]
2    (2.667, 4.333]
3    (2.667, 4.333]
4      (4.333, 6.0]
5      (4.333, 6.0]
dtype: category
Categories (3, interval[float64, right]): [(0.995, 2.667] < (2.667, 4.333] < (4.333, 6.0]]

In [42]: pd.Series([1, 2, 3, 2, 2, 3]).astype("category")
Out[42]: 
0    1
1    2
2    3
3    2
4    2
5    3
dtype: category
Categories (3, int64): [1, 2, 3] 

更多细节和示例请参见分类介绍和 API 文档。还有关于 R 的因子的差异的文档。

meltarray

在 R 中使用名为a的三维数组的表达式,你想要将其融化成数据框:

a  <-  array(c(1:23,  NA),  c(2,3,4))
data.frame(melt(a)) 

在 Python 中,由于a是一个列表,你可以简单地使用列表推导式。

In [28]: a = np.array(list(range(1, 24)) + [np.NAN]).reshape(2, 3, 4)

In [29]: pd.DataFrame([tuple(list(x) + [val]) for x, val in np.ndenumerate(a)])
Out[29]: 
 0  1  2     3
0   0  0  0   1.0
1   0  0  1   2.0
2   0  0  2   3.0
3   0  0  3   4.0
4   0  1  0   5.0
.. .. .. ..   ...
19  1  1  3  20.0
20  1  2  0  21.0
21  1  2  1  22.0
22  1  2  2  23.0
23  1  2  3   NaN

[24 rows x 4 columns] 

meltlist

在 R 中使用名为a的列表的表达式,你想要将其融化成数据框:

a  <-  as.list(c(1:4,  NA))
data.frame(melt(a)) 

在 Python 中,这个列表将是一个元组的列表,所以DataFrame()方法会将其转换为所需的数据框。

In [30]: a = list(enumerate(list(range(1, 5)) + [np.NAN]))

In [31]: pd.DataFrame(a)
Out[31]: 
 0    1
0  0  1.0
1  1  2.0
2  2  3.0
3  3  4.0
4  4  NaN 

更多详细信息和示例请参见数据结构介绍文档。

meltdf

在 R 中使用名为cheese的数据框进行数据重塑的表达式:

cheese  <-  data.frame(
  first  =  c('John',  'Mary'),
  last  =  c('Doe',  'Bo'),
  height  =  c(5.5,  6.0),
  weight  =  c(130,  150)
)
melt(cheese,  id=c("first",  "last")) 

在 Python 中,melt()方法相当于 R 中的:

In [32]: cheese = pd.DataFrame(
 ....:    {
 ....:        "first": ["John", "Mary"],
 ....:        "last": ["Doe", "Bo"],
 ....:        "height": [5.5, 6.0],
 ....:        "weight": [130, 150],
 ....:    }
 ....: )
 ....: 

In [33]: pd.melt(cheese, id_vars=["first", "last"])
Out[33]: 
 first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0

In [34]: cheese.set_index(["first", "last"]).stack(future_stack=True)  # alternative way
Out[34]: 
first  last 
John   Doe   height      5.5
 weight    130.0
Mary   Bo    height      6.0
 weight    150.0
dtype: float64 

更多详细信息和示例请参见重塑文档。

cast

在 R 中,acast是使用名为df的数据框进行高维数组转换的表达式:

df  <-  data.frame(
  x  =  runif(12,  1,  168),
  y  =  runif(12,  7,  334),
  z  =  runif(12,  1.7,  20.7),
  month  =  rep(c(5,6,7),4),
  week  =  rep(c(1,2),  6)
)

mdf  <-  melt(df,  id=c("month",  "week"))
acast(mdf,  week  ~  month  ~  variable,  mean) 

在 Python 中,最佳方式是利用pivot_table()

In [35]: df = pd.DataFrame(
 ....:    {
 ....:        "x": np.random.uniform(1.0, 168.0, 12),
 ....:        "y": np.random.uniform(7.0, 334.0, 12),
 ....:        "z": np.random.uniform(1.7, 20.7, 12),
 ....:        "month": [5, 6, 7] * 4,
 ....:        "week": [1, 2] * 6,
 ....:    }
 ....: )
 ....: 

In [36]: mdf = pd.melt(df, id_vars=["month", "week"])

In [37]: pd.pivot_table(
 ....:    mdf,
 ....:    values="value",
 ....:    index=["variable", "week"],
 ....:    columns=["month"],
 ....:    aggfunc="mean",
 ....: )
 ....: 
Out[37]: 
month                  5           6           7
variable week 
x        1     93.888747   98.762034   55.219673
 2     94.391427   38.112932   83.942781
y        1     94.306912  279.454811  227.840449
 2     87.392662  193.028166  173.899260
z        1     11.016009   10.079307   16.170549
 2      8.476111   17.638509   19.003494 

类似于dcast,它使用 R 中名为df的数据框根据AnimalFeedType聚合信息:

df  <-  data.frame(
  Animal  =  c('Animal1',  'Animal2',  'Animal3',  'Animal2',  'Animal1',
  'Animal2',  'Animal3'),
  FeedType  =  c('A',  'B',  'A',  'A',  'B',  'B',  'A'),
  Amount  =  c(10,  7,  4,  2,  5,  6,  2)
)

dcast(df,  Animal  ~  FeedType,  sum,  fill=NaN)
# Alternative method using base R
with(df,  tapply(Amount,  list(Animal,  FeedType),  sum)) 

Python 可以通过两种不同的方式来实现。首先,类似于上面使用pivot_table()

In [38]: df = pd.DataFrame(
 ....:    {
 ....:        "Animal": [
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:            "Animal2",
 ....:            "Animal1",
 ....:            "Animal2",
 ....:            "Animal3",
 ....:        ],
 ....:        "FeedType": ["A", "B", "A", "A", "B", "B", "A"],
 ....:        "Amount": [10, 7, 4, 2, 5, 6, 2],
 ....:    }
 ....: )
 ....: 

In [39]: df.pivot_table(values="Amount", index="Animal", columns="FeedType", aggfunc="sum")
Out[39]: 
FeedType     A     B
Animal 
Animal1   10.0   5.0
Animal2    2.0  13.0
Animal3    6.0   NaN 

第二种方法是使用groupby()方法:

In [40]: df.groupby(["Animal", "FeedType"])["Amount"].sum()
Out[40]: 
Animal   FeedType
Animal1  A           10
 B            5
Animal2  A            2
 B           13
Animal3  A            6
Name: Amount, dtype: int64 

更多详细信息和示例请参见重塑文档或分组文档。

factor

pandas 有一种用于分类数据的数据类型。

cut(c(1,2,3,4,5,6),  3)
factor(c(1,2,3,2,2,3)) 

在 pandas 中,可以通过pd.cutastype("category")来实现:

In [41]: pd.cut(pd.Series([1, 2, 3, 4, 5, 6]), 3)
Out[41]: 
0    (0.995, 2.667]
1    (0.995, 2.667]
2    (2.667, 4.333]
3    (2.667, 4.333]
4      (4.333, 6.0]
5      (4.333, 6.0]
dtype: category
Categories (3, interval[float64, right]): [(0.995, 2.667] < (2.667, 4.333] < (4.333, 6.0]]

In [42]: pd.Series([1, 2, 3, 2, 2, 3]).astype("category")
Out[42]: 
0    1
1    2
2    3
3    2
4    2
5    3
dtype: category
Categories (3, int64): [1, 2, 3] 

更多详细信息和示例请参见分类介绍和 API 文档。还有一份关于 R 中因子的差异的文档。

posted @ 2024-06-26 10:38  绝不原创的飞龙  阅读(416)  评论(0)    收藏  举报