快速开始 Pandas|了解 Pandas 的数据结构并实现常用的表格操作

在线调试运行

目标

了解 Pandas 的数据结构并实现常用的表格操作。

在学习本教程后,你将能够:

  • 了解 Pandas 的数据结构对象
  • 使用 Pandas 创建、读取或导出数据
  • 查看或选择数据,对数据进行处理(选择,删除,分组,分类等)
  • 表格处理,例如多表合并,改变表的数据结构
  • 使用 Pandas 时间序列数据
  • 结合 matplotlib 对 Pandas 数据进行绘图

阅读该教程【最多】约需 15 分钟,让我们开始吧!

目录

背景

这是对 Pandas 的简短介绍,主要面向新用户。您可以在这里查看更进一步的教程。

你需要提前掌握以下知识:

  • 非常基本的 Python 知识

实践

1 认识 Pandas

在这一部分,你会了解什么是 Pandas,在 Bohrium 中使用 Pandas,验证安装并查看版本。

1.1 什么是 Pandas

Pandas 是一个用于处理数据集的 Python 库。它具有分析、清理、探索和操作数据的功能。 “Pandas”这个名称参考了“Panel Data”和“Python Data Analysis”,由 Wes McKinney 于 2008 年创建。Pandas 广泛用于数据科学、数据分析和机器学习任务。

官方强调了其如下显著特点[4]:

  • 轻松处理浮点数和非浮点数中的 缺失数据(表示为 NaNNANaT

  • 大小可变性:可以从 DataFrame 和更高维度的对象中插入和删除 列。

  • 自动和显式数据对齐,对象可以显式地对齐到一组标签,或者用户可以简单地忽略标签,让 Series、DataFrame 等在计算中自动对齐数据。

  • 提供了强大、灵活的分组功能,可以对数据集执行分割-应用-组合操作,用于聚合和转换数据。

  • 以将 Python 和 NumPy 数据结构中的不同索引、不规则数据轻松转换为 DataFrame 对象。

  • 智能的基于标签的切片花式索引子集,可用于大型数据集。

  • 直观的合并连接数据集的方法。

  • 数据集的灵活重塑透视

  • 轴的分层标签(每个刻度可以有多个标签)

  • 强大的 IO 工具,可从平面文件(CSV 和分隔符)、Excel 文件、数据库加载数据,并从超快的 HDF5 格式保存/加载数据

  • 时间序列特定功能:日期范围生成和频率转换、移动窗口统计、日期移位和滞后

1.2 安装 Pandas

本教程是一个 Bohrium Notebook。Python 程序可直接在浏览器中运行,Bohrium 已安装 Pandas

要按照本教程进行操作,请点击本页顶部的按钮,在 Bohrium Notebook 中运行本笔记本。

  1. 你可以点击界面上方蓝色按钮 开始连接,选择 bohrium-notebook:2023-02-28 镜像及任何一款计算机型,稍等片刻即可运行。

  2. 若要运行笔记本中的所有代码,请点击左上角“ 运行全部单元格 ”。若要一次运行一个代码单元,请选择需要运行的单元格,然后点击左上角 “运行选中的单元格” 图标。

如果你的 Bohrium 镜像尚未安装 Pandas, 最方便的方法是通过 pip 安装:

! pip install pandas
Requirement already satisfied: pandas in /opt/anaconda3/envs/ML_env/lib/python3.9/site-packages (1.5.1)
Requirement already satisfied: python-dateutil>=2.8.1 in /Users/harvey/.local/lib/python3.9/site-packages (from pandas) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /opt/anaconda3/envs/ML_env/lib/python3.9/site-packages (from pandas) (2022.1)
Requirement already satisfied: numpy>=1.20.3 in /opt/anaconda3/envs/ML_env/lib/python3.9/site-packages (from pandas) (1.23.4)
Requirement already satisfied: six>=1.5 in /opt/anaconda3/envs/ML_env/lib/python3.9/site-packages (from python-dateutil>=2.8.1->pandas) (1.16.0)

如果你需要使用更特定于你的平台或包管理器的安装方法,你可以在这里查看更完整的安装说明。

1.3 验证 Pandas 安装并查看版本

安装 Pandas 后,确认库已成功安装并且你可以开始使用它。

不要跳过此步骤。

如果 Pandas 未正确安装或在此步骤中引发错误,则将无法运行之后的示例。

import pandas as pd
print(pd.__version__)  # pd.__version__ 返回安装的 Pandas 的版本号
1.5.1

2 Pandas 方法

在这一节中,你会了解到一些 Pandas 的基础方法,包括:

  • 2.1 创建对象
  • 2.2 查看数据
  • 2.3 选择数据
  • 2.4 删除缺失值
  • 2.5 操作数据
  • 2.6 合并表格
  • 2.7 数据分组
  • 2.8 改变数据结构
  • 2.9 时间序列
  • 2.10 分类数据
  • 2.11 绘图
  • 2.12 读取与导出数据
2.1 创建对象

Pandas 的数据对象分为两类,一类为 Series,一类为 DataFrame

Series 是一个一维标记数组,能够保存任何数据类型(整数、字符串、浮点数、Python 对象等)。轴标签统称为索引。

DataFrame 是一种二维标记的数据结构,具有可能不同类型的列。您可以将其视为电子表格或SQL表,或系列对象的字典。它通常是最常用的 Pandas 对象。

查看更多 Pandas 数据结构的信息,请阅读 Intro to data structures

2.1.1 创建一个 Series

通过传递一个值列表,让 Pandas 创建一个默认的整数索引。

import pandas as pd
import numpy as np

s = pd.Series([1, 3, 5, np.nan, 6, 8])
s
0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64
2.1.2 创建一个 DataFrame (方法 1)

通过传递一个 NumPy 数组,使用 date_range() 创建一个日期时间索引,并使用标记列进行标记。

dates = pd.date_range("20130101", periods=6)
dates
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
               '2013-01-05', '2013-01-06'],
              dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
df
ABCD
2013-01-010.7326490.4529110.0504170.234816
2013-01-02-1.1273601.0240672.3554110.834325
2013-01-03-0.346012-1.059302-0.927076-0.518720
2013-01-040.793778-0.880850-0.1403221.771748
2013-01-05-0.4658720.074124-0.884347-0.125452
2013-01-060.865522-0.773847-1.754687-1.171656
2.1.3 创建一个 DataFrame (方法 2)

通过传递一个可以转换为类似于 Series 的结构的对象字典。

df2 = pd.DataFrame(
        {
            "A": 1.0,
            "B": pd.Timestamp("20130102"),
            "C": pd.Series(1, index=list(range(4)), dtype="float32"),
            "D": np.array([3] * 4, dtype="int32"),
            "E": pd.Categorical(["test", "train", "test", "train"]),
            "F": "foo",
        }
    )

df2
ABCDEF
01.02013-01-021.03testfoo
11.02013-01-021.03trainfoo
21.02013-01-021.03testfoo
31.02013-01-021.03trainfoo
# 生成的 DataFrame 的列具有不同的 dtype:
df2.dtypes
A           float64
B    datetime64[ns]
C           float32
D             int32
E          category
F            object
dtype: object

如果您正在使用 IPython,列名(以及公共属性)的 tab 补全会自动启用。在这个例子中,您可以使用 df2. 后跟 tab 键来查看可以自动补全的属性列表。

In [12] df2.<TAB>
df2.A                  df2.bool
df2.abs                df2.boxplot
df2.add                df2.C
df2.add_prefix         df2.clip
df2.add_suffix         df2.columns
df2.align              df2.copy
df2.all                df2.count
df2.any                df2.combine
df2.append             df2.D
df2.apply              df2.describe
df2.applymap           df2.diff
df2.B                  df2.duplicated

在这个例子中,列 A, B, C, 和 D 是可以自动补全的属性。E 和 F 也在列表中,但是为了简洁起见,其余的属性被截断了。

2.2 查看数据

您可以使用 DataFrame.head()DataFrame.tail() 分别查看 DataFrame 的前几行和后几行:

df.head()
ABCD
2013-01-010.7326490.4529110.0504170.234816
2013-01-02-1.1273601.0240672.3554110.834325
2013-01-03-0.346012-1.059302-0.927076-0.518720
2013-01-040.793778-0.880850-0.1403221.771748
2013-01-05-0.4658720.074124-0.884347-0.125452
df.tail(3)
ABCD
2013-01-040.793778-0.880850-0.1403221.771748
2013-01-05-0.4658720.074124-0.884347-0.125452
2013-01-060.865522-0.773847-1.754687-1.171656

使用 DataFrame.index 或 DataFrame.columns 显示 DataFrame 的索引或列:

df.index
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
               '2013-01-05', '2013-01-06'],
              dtype='datetime64[ns]', freq='D')
df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')

DataFrame.to_numpy() 给出了底层数据的 NumPy 表示。

请注意,当 DataFrame 具有不同数据类型的列时,这可能是一个昂贵的操作,

这归结于 pandas 和 NumPy 之间的根本差异:NumPy 数组对于整个数组只有一个 dtype,而 pandas DataFrame 对于每个列都有一个 dtype。当

您调用 DataFrame.to_numpy() 时,pandas 将找到可以容纳 DataFrame 中所有 dtype 的 NumPy dtype。

这可能最终是 object,这需要将每个值转换为 Python 对象。

对于 df,DataFrame 中全是浮点数,DataFrame.to_numpy() 很快,不需要复制数据:

from time import time
import datetime

start1 = time()
df.to_numpy()
time1 = time()-start1
interval1 = datetime.datetime.fromtimestamp(time1).strftime("%M:%S:%f")  # 查看计算所用时间
interval1
'00:00:000313'

对于 df2,DataFrame 中有许多类型,DataFrame.to_numpy() 是个昂贵的操作:

start2 = time()
df2.to_numpy()
time2 = time()-start2
interval2 = datetime.datetime.fromtimestamp(time2).strftime("%M:%S:%f")  # 查看计算所用时间

print(interval2)
print(f'所用时间是上一步的 {np.divide(time2, time1):.3f} 倍')
00:00:002456
所用时间是上一步的 7.846 倍

注意

DataFrame.to_numpy() 在输出中不包含索引或列标签。

2.3 选择数据
# 我们可以使用不同的方式来选择 DataFrame 中的数据。例如,选择一个单独的列:
df['A']

2013-01-01    0.732649
2013-01-02   -1.127360
2013-01-03   -0.346012
2013-01-04    0.793778
2013-01-05   -0.465872
2013-01-06    0.865522
Freq: D, Name: A, dtype: float64
# 或者选择行的切片:

df[0:3]

ABCD
2013-01-010.7326490.4529110.0504170.234816
2013-01-02-1.1273601.0240672.3554110.834325
2013-01-03-0.346012-1.059302-0.927076-0.518720
# 或者通过标签选择:

df.loc[dates[0]]

A    0.732649
B    0.452911
C    0.050417
D    0.234816
Name: 2013-01-01 00:00:00, dtype: float64
# 或者通过标签在多个轴上选择:

df.loc[:, ['A', 'B']]

AB
2013-01-010.7326490.452911
2013-01-02-1.1273601.024067
2013-01-03-0.346012-1.059302
2013-01-040.793778-0.880850
2013-01-05-0.4658720.074124
2013-01-060.865522-0.773847
# 或者通过位置选择:

df.iloc[3]

A    0.793778
B   -0.880850
C   -0.140322
D    1.771748
Name: 2013-01-04 00:00:00, dtype: float64
# 或者通过位置在多个轴上选择:

df.iloc[3:5, 0:2]

AB
2013-01-040.793778-0.880850
2013-01-05-0.4658720.074124
# 或者通过一个布尔数组来选择:

df[df.A > 0]

ABCD
2013-01-010.7326490.4529110.0504170.234816
2013-01-040.793778-0.880850-0.1403221.771748
2013-01-060.865522-0.773847-1.754687-1.171656
# 或者通过 isin() 方法来过滤:

df2 = df.copy()
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
df2[df2['E'].isin(['two', 'four'])]
ABCDE
2013-01-03-0.346012-1.059302-0.927076-0.518720two
2013-01-05-0.4658720.074124-0.884347-0.125452four
2.4 缺失值操作

pandas提供了一些方法来处理缺失值。要删除缺失值,您可以使用以下代码:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f', 'h'], columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(df)
print('-------------------------------')
print(df.dropna())
        one       two     three
a  0.228386  0.244739 -1.583778
b       NaN       NaN       NaN
c  0.292575 -0.115925 -0.140590
d       NaN       NaN       NaN
e  0.367375  0.202992 -0.190355
f -0.581880  1.325593  1.040521
g       NaN       NaN       NaN
h -1.566352 -1.547750  0.614942
-------------------------------
        one       two     three
a  0.228386  0.244739 -1.583778
c  0.292575 -0.115925 -0.140590
e  0.367375  0.202992 -0.190355
f -0.581880  1.325593  1.040521
h -1.566352 -1.547750  0.614942

这将创建一个DataFrame,其中包含一些随机数字和NaN值。然后,它将删除所有包含NaN值的行。

要替换缺失值,您可以使用以下代码:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f', 'h'], columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(df)
print('-'*50)
print(df.fillna(0))

        one       two     three
a  1.042368  0.745451  1.395693
b       NaN       NaN       NaN
c -0.339838  0.632446  2.070172
d       NaN       NaN       NaN
e -0.245898  0.858535  0.376770
f  0.792838 -0.569140  0.012835
g       NaN       NaN       NaN
h  0.530681 -0.215863 -0.145303
--------------------------------------------------
        one       two     three
a  1.042368  0.745451  1.395693
b  0.000000  0.000000  0.000000
c -0.339838  0.632446  2.070172
d  0.000000  0.000000  0.000000
e -0.245898  0.858535  0.376770
f  0.792838 -0.569140  0.012835
g  0.000000  0.000000  0.000000
h  0.530681 -0.215863 -0.145303

这将创建一个DataFrame,其中包含一些随机数字和NaN值。然后,它将使用0替换所有NaN值。

2.5 操作数据
2.5.1 统计

pandas有一些内置方法,可以很容易地计算统计信息,例如平均值,总和和最小值。默认情况下,这些方法排除缺失值。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f', 'h'], columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(df)
print('-'*50)
print(df.mean())
        one       two     three
a -0.330677 -0.696890  0.177158
b       NaN       NaN       NaN
c -0.770930 -1.848735 -1.065606
d       NaN       NaN       NaN
e -0.664989  0.596805 -0.309245
f -0.510950  1.562430  1.541852
g       NaN       NaN       NaN
h -0.038146 -0.082760 -1.090831
--------------------------------------------------
one     -0.463138
two     -0.093830
three   -0.149334
dtype: float64

这将创建一个DataFrame,其中包含一些随机数字。然后,它将计算每列的平均值。

您还可以使用其他方法,例如sum,cumsum和describe:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f', 'h'], columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(df)
print('-'*50)
print(df.sum())
print('-'*50)
print(df.cumsum())
print('-'*50)
print(df.describe())
        one       two     three
a  1.094430 -1.051135  0.799771
b       NaN       NaN       NaN
c -0.241605 -1.196541 -0.836143
d       NaN       NaN       NaN
e  0.606664  0.187086 -0.293555
f  0.003697  1.398083 -0.864984
g       NaN       NaN       NaN
h  0.089101 -1.088488  0.313684
--------------------------------------------------
one      1.552287
two     -1.750996
three   -0.881227
dtype: float64
--------------------------------------------------
        one       two     three
a  1.094430 -1.051135  0.799771
b       NaN       NaN       NaN
c  0.852825 -2.247676 -0.036372
d       NaN       NaN       NaN
e  1.459489 -2.060591 -0.329927
f  1.463185 -0.662508 -1.194911
g       NaN       NaN       NaN
h  1.552287 -1.750996 -0.881227
--------------------------------------------------
            one       two     three
count  5.000000  5.000000  5.000000
mean   0.310457 -0.350199 -0.176245
std    0.536242  1.128920  0.727362
min   -0.241605 -1.196541 -0.864984
25%    0.003697 -1.088488 -0.836143
50%    0.089101 -1.051135 -0.293555
75%    0.606664  0.187086  0.313684
max    1.094430  1.398083  0.799771

这将创建一个DataFrame,其中包含一些随机数字。然后,它将计算每列的总和,累积总和和描述性统计信息。

2.5.2 apply 方法

在 pandas 中,apply 方法是一种非常有用的方法,它可以将函数应用于 DataFrame 的行或列。例如,您可以使用 apply 方法计算每行或每列的总和,平均值或其他统计信息。

df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'b', 'c', 'd', 'e'], columns=['one', 'two', 'three'])
print(df)
print('-' * 50)
print(df.apply(np.mean))
print('-' * 50)
print(df.apply(np.sum, axis=1))

        one       two     three
a  1.836104 -0.413132 -1.327340
b  0.459524  0.484854  0.975912
c -0.139497 -0.821099  0.519994
d  0.940098 -0.732839  0.125682
e -0.244552  1.931906  0.761521
--------------------------------------------------
one      0.570335
two      0.089938
three    0.211154
dtype: float64
--------------------------------------------------
a    0.095632
b    1.920290
c   -0.440601
d    0.332941
e    2.448875
dtype: float64

这将创建一个DataFrame,其中包含一些随机数字。然后,它将使用apply方法计算每列的平均值和每行的总和。

2.5.3 直方图

直方图可以用于直观地查看数据分布。 以下是如何使用 matplotlib 绘制直方图的示例。


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 创建一个Series
s = pd.Series(np.random.randint(0, 7, size=10))
print(s.value_counts())
# 绘制直方图
s.hist(bins=20)

4    3
1    3
0    2
5    1
3    1
dtype: int64





<AxesSubplot:>




<Figure size 640x480 with 1 Axes>

在Series上调用hist方法将自动绘制直方图。 可以指定bins参数以控制直方图中的箱数。

请注意,hist方法还可以在DataFrame上调用。 在这种情况下,每列的直方图将绘制在单独的子图中。

请访问直方图以获取更多信息。

2.5.4 字符串方法

Series对象在str属性中配备了一组字符串处理方法,可以轻松地对数组的每个元素进行操作,如下面的代码片段所示。

s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])

# 调用str方法
print(s)
print('-' * 50)
print(s.str.lower())

0       A
1       B
2       C
3    Aaba
4    Baca
5     NaN
6    CABA
7     dog
8     cat
dtype: object
--------------------------------------------------
0       a
1       b
2       c
3    aaba
4    baca
5     NaN
6    caba
7     dog
8     cat
dtype: object

请注意,当数据中存在NaN时,它们将自动跳过。

请访问字符串方法以获取更多信息。

2.6 合并表格
2.6.1 Concat

concat 是 pandas 中的一个函数,它可以将多个 pandas 对象(如 DataFrame 或 Series)沿着一个轴(通常是行轴)进行连接。

下面是一个简单的例子:


import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.ones((3, 4)) * 0, columns=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame(np.ones((3, 4)) * 1, columns=['a', 'b', 'c', 'd'])
df3 = pd.DataFrame(np.ones((3, 4)) * 2, columns=['a', 'b', 'c', 'd'])

res = pd.concat([df1, df2, df3], axis=0, ignore_index=True)
print(res)
     a    b    c    d
0  0.0  0.0  0.0  0.0
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  1.0  1.0  1.0  1.0
4  1.0  1.0  1.0  1.0
5  1.0  1.0  1.0  1.0
6  2.0  2.0  2.0  2.0
7  2.0  2.0  2.0  2.0
8  2.0  2.0  2.0  2.0

注意

在 pandas 中,向 DataFrame 添加列是相对较快的。但是,添加行需要进行复制,可能会很昂贵。我们建议将预先构建的记录列表传递给 DataFrame 构造函数,而不是通过迭代地将记录附加到 DataFrame 中来构建 DataFrame。

2.6.2 Join

在 Pandas 中,有两种主要的用于合并数据的方法:merge 和 join。

merge 函数允许您根据一个或多个键将不同 DataFrame 对象中的行连接起来。这种操作类似于 SQL 中的 JOIN 操作。

例如,假设我们有两个 DataFrame 对象:

left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
print(left)
print('-' * 50)
print(right)

   key  lval
0  foo     1
1  bar     2
--------------------------------------------------
   key  rval
0  foo     4
1  bar     5

我们可以使用 merge 函数将它们合并在一起:

merged = pd.merge(left, right, on='key')
merged
keylvalrval
0foo14
1bar25

另一种常用的数据合并方法是 join。DataFrame 具有一个方便的 join 实例方法,它可以快速将不同 DataFrame 对象中具有相同或相似索引的行连接在一起。

例如,假设我们有两个 DataFrame 对象:

left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                     'B': ['B0', 'B1', 'B2']},
                    index=['K0', 'K1', 'K2'])

right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
                      'D': ['D0', 'D2', 'D3']},
                     index=['K0', 'K2', 'K3'])

left
AB
K0A0B0
K1A1B1
K2A2B2
right
CD
K0C0D0
K2C2D2
K3C3D3

我们可以使用 join 方法将它们连接在一起:

joined = left.join(right)
joined
ABCD
K0A0B0C0D0
K1A1B1NaNNaN
K2A2B2C2D2
2.7 数据分组

在 Pandas 中,要完成数据的分组操作,需要使用 groupby() 函数,它和 SQL 的 GROUP BY 操作非常相似。在划分出来的组(group)上应用一些统计函数,从而达到数据分析的目的,比如对分组数据进行聚合、转换,或者过滤。这个过程主要包含以下三步:

分割:按照一些规则将数据分成不同的组。

应用:对于每组数据分别执行一个函数。

合并:将每组的结果合并成一个数据结构。

下面是一个简单的例子:

df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar',
                         'foo', 'bar', 'foo', 'foo'],
                   'B': ['one', 'one', 'two', 'three',
                         'two', 'two', 'one', 'three'],
                   'C': np.random.randn(8),
                   'D': np.random.randn(8)})
                   
df
ABCD
0fooone-1.250990-0.561155
1barone0.558040-0.715369
2footwo-1.1766162.087695
3barthree-0.695511-1.438845
4footwo0.712811-1.133881
5bartwo0.3813690.166263
6fooone0.8815261.149048
7foothree-1.520854-1.484507

分组,然后将 sum() 函数应用于生成的组:

df.groupby("A")[["C", "D"]].sum()
CD
A
bar0.243898-1.987951
foo-2.3541240.057199

按多列分组形成一个分层索引,我们可以再次应用 sum() 函数:

df.groupby(["A", "B"]).sum()
CD
AB
barone0.558040-0.715369
three-0.695511-1.438845
two0.3813690.166263
fooone-0.3694640.587893
three-1.520854-1.484507
two-0.4638050.953814
2.8 改变数据结构

好的,这是您要求的翻译:

在 Pandas 中,有几种方法可以对数据进行重塑和透视。

一种常用的方法是使用 stack 方法。此方法“压缩” DataFrame 的列级别,返回具有多层索引的 Series 对象。

例如,假设我们有一个 DataFrame 对象:


tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
                     'foo', 'foo', 'qux', 'qux'],
                    ['one', 'two', 'one', 'two',
                     'one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])

df
AB
firstsecond
barone-0.695612-0.253276
two-1.4579820.575581
bazone-0.8015581.118211
two0.4865850.804642
fooone1.9045470.520693
two-0.9252260.494819
quxone0.1967891.234989
two0.575095-1.960254

我们可以使用 stack 方法将其转换为多层索引的 Series 对象:

stacked = df.stack()
stacked
first  second   
bar    one     A   -0.695612
               B   -0.253276
       two     A   -1.457982
               B    0.575581
baz    one     A   -0.801558
               B    1.118211
       two     A    0.486585
               B    0.804642
foo    one     A    1.904547
               B    0.520693
       two     A   -0.925226
               B    0.494819
qux    one     A    0.196789
               B    1.234989
       two     A    0.575095
               B   -1.960254
dtype: float64

另一种常用的重塑方法是使用 pivot 函数。此函数允许您根据给定列中的值创建新的 DataFrame,并使用另一列中的唯一值作为新 DataFrame 的列。

例如,假设我们有一个 DataFrame 对象:

df = pd.DataFrame(
         {
            "A": ["one", "one", "two", "three"] * 3,
           "B": ["A", "B", "C"] * 4,
            "C": ["foo", "foo", "foo", "bar", "bar", "bar"] * 2,
            "D": np.random.randn(12),
            "E": np.random.randn(12),
        }
    )

df
ABCDE
0oneAfoo-1.2292081.632380
1oneBfoo0.707761-0.664045
2twoCfoo0.6489491.175932
3threeAbar-0.740921-0.358632
4oneBbar-1.3390200.585905
5oneCbar0.4566941.036741
6twoAfoo0.337801-0.642565
7threeBfoo-0.548544-0.707633
8oneCfoo-0.1070390.311032
9oneAbar-1.5554310.226431
10twoBbar2.6622710.630751
11threeCbar0.3728970.521987

我们可以使用 pivot 函数将其转换为新的 DataFrame:

pd.pivot_table(df, values="D", index=["A", "B"], columns=["C"])
Cbarfoo
AB
oneA-1.555431-1.229208
B-1.3390200.707761
C0.456694-0.107039
threeA-0.740921NaN
BNaN-0.548544
C0.372897NaN
twoANaN0.337801
B2.662271NaN
CNaN0.648949
2.9 时间序列

Pandas在执行频率转换(例如将秒数据转换为5分钟数据)期间具有简单,强大和高效的功能。这在金融应用中非常常见,但不仅限于此。您可以在Pandas文档的时间序列部分中找到更多信息。链接为https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html。

rng = pd.date_range("1/1/2012", periods=100, freq="S")
rng

DatetimeIndex(['2012-01-01 00:00:00', '2012-01-01 00:00:01',
               '2012-01-01 00:00:02', '2012-01-01 00:00:03',
               '2012-01-01 00:00:04', '2012-01-01 00:00:05',
               '2012-01-01 00:00:06', '2012-01-01 00:00:07',
               '2012-01-01 00:00:08', '2012-01-01 00:00:09',
               '2012-01-01 00:00:10', '2012-01-01 00:00:11',
               '2012-01-01 00:00:12', '2012-01-01 00:00:13',
               '2012-01-01 00:00:14', '2012-01-01 00:00:15',
               '2012-01-01 00:00:16', '2012-01-01 00:00:17',
               '2012-01-01 00:00:18', '2012-01-01 00:00:19',
               '2012-01-01 00:00:20', '2012-01-01 00:00:21',
               '2012-01-01 00:00:22', '2012-01-01 00:00:23',
               '2012-01-01 00:00:24', '2012-01-01 00:00:25',
               '2012-01-01 00:00:26', '2012-01-01 00:00:27',
               '2012-01-01 00:00:28', '2012-01-01 00:00:29',
               '2012-01-01 00:00:30', '2012-01-01 00:00:31',
               '2012-01-01 00:00:32', '2012-01-01 00:00:33',
               '2012-01-01 00:00:34', '2012-01-01 00:00:35',
               '2012-01-01 00:00:36', '2012-01-01 00:00:37',
               '2012-01-01 00:00:38', '2012-01-01 00:00:39',
               '2012-01-01 00:00:40', '2012-01-01 00:00:41',
               '2012-01-01 00:00:42', '2012-01-01 00:00:43',
               '2012-01-01 00:00:44', '2012-01-01 00:00:45',
               '2012-01-01 00:00:46', '2012-01-01 00:00:47',
               '2012-01-01 00:00:48', '2012-01-01 00:00:49',
               '2012-01-01 00:00:50', '2012-01-01 00:00:51',
               '2012-01-01 00:00:52', '2012-01-01 00:00:53',
               '2012-01-01 00:00:54', '2012-01-01 00:00:55',
               '2012-01-01 00:00:56', '2012-01-01 00:00:57',
               '2012-01-01 00:00:58', '2012-01-01 00:00:59',
               '2012-01-01 00:01:00', '2012-01-01 00:01:01',
               '2012-01-01 00:01:02', '2012-01-01 00:01:03',
               '2012-01-01 00:01:04', '2012-01-01 00:01:05',
               '2012-01-01 00:01:06', '2012-01-01 00:01:07',
               '2012-01-01 00:01:08', '2012-01-01 00:01:09',
               '2012-01-01 00:01:10', '2012-01-01 00:01:11',
               '2012-01-01 00:01:12', '2012-01-01 00:01:13',
               '2012-01-01 00:01:14', '2012-01-01 00:01:15',
               '2012-01-01 00:01:16', '2012-01-01 00:01:17',
               '2012-01-01 00:01:18', '2012-01-01 00:01:19',
               '2012-01-01 00:01:20', '2012-01-01 00:01:21',
               '2012-01-01 00:01:22', '2012-01-01 00:01:23',
               '2012-01-01 00:01:24', '2012-01-01 00:01:25',
               '2012-01-01 00:01:26', '2012-01-01 00:01:27',
               '2012-01-01 00:01:28', '2012-01-01 00:01:29',
               '2012-01-01 00:01:30', '2012-01-01 00:01:31',
               '2012-01-01 00:01:32', '2012-01-01 00:01:33',
               '2012-01-01 00:01:34', '2012-01-01 00:01:35',
               '2012-01-01 00:01:36', '2012-01-01 00:01:37',
               '2012-01-01 00:01:38', '2012-01-01 00:01:39'],
              dtype='datetime64[ns]', freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
ts
2012-01-01 00:00:00    343
2012-01-01 00:00:01    400
2012-01-01 00:00:02    408
2012-01-01 00:00:03    372
2012-01-01 00:00:04    475
                      ... 
2012-01-01 00:01:35    430
2012-01-01 00:01:36    472
2012-01-01 00:01:37    417
2012-01-01 00:01:38    273
2012-01-01 00:01:39    196
Freq: S, Length: 100, dtype: int64
ts.resample("5Min").sum()
2012-01-01    26038
Freq: 5T, dtype: int64

Series.tz_localize()方法用于将 Series 或 DataFrame 的 tz-naive 索引本地化到目标时区。

rng = pd.date_range("3/6/2012 00:00", periods=5, freq="D")
ts = pd.Series(np.random.randn(len(rng)), rng)
ts_utc = ts.tz_localize("UTC")
ts_utc
2012-03-06 00:00:00+00:00   -0.182367
2012-03-07 00:00:00+00:00    0.137739
2012-03-08 00:00:00+00:00   -0.219611
2012-03-09 00:00:00+00:00   -0.447437
2012-03-10 00:00:00+00:00   -0.312121
Freq: D, dtype: float64

Series.tz_convert()方法用于处理时区感知的索引。它将tz-aware轴转换为目标时区。

ts_utc.tz_convert("US/Eastern")
2012-03-05 19:00:00-05:00   -0.182367
2012-03-06 19:00:00-05:00    0.137739
2012-03-07 19:00:00-05:00   -0.219611
2012-03-08 19:00:00-05:00   -0.447437
2012-03-09 19:00:00-05:00   -0.312121
Freq: D, dtype: float64

Pandas使用Timestamp实例和DatetimeIndex实例来表示时间戳和时间戳序列。对于常规时间跨度,Pandas使用Period对象表示标量值,使用PeriodIndex表示跨度序列。

rng = pd.date_range("1/1/2012", periods=5, freq="M")
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2012-01-31   -0.364667
2012-02-29   -0.677385
2012-03-31    0.400009
2012-04-30   -0.459159
2012-05-31   -1.058427
Freq: M, dtype: float64
ps = ts.to_period()
ps
2012-01   -0.364667
2012-02   -0.677385
2012-03    0.400009
2012-04   -0.459159
2012-05   -1.058427
Freq: M, dtype: float64
ps.to_timestamp()
2012-01-01   -0.364667
2012-02-01   -0.677385
2012-03-01    0.400009
2012-04-01   -0.459159
2012-05-01   -1.058427
Freq: MS, dtype: float64

将周期和时间戳之间的转换可以使用一些方便的算术函数。在下面的示例中,我们将以11月结束的年度季度频率转换为季度结束后的下个月的9点钟。1。这里的周期是指Pandas中的Period对象,时间戳是指Pandas中的Timestamp对象

prng = pd.period_range("1990Q1", "2000Q4", freq="Q-NOV")
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq("M", "e") + 1).asfreq("H", "s") + 9
ts.head()
1990-03-01 09:00    0.783871
1990-06-01 09:00   -0.067191
1990-09-01 09:00    0.459511
1990-12-01 09:00    2.081520
1991-03-01 09:00    1.226343
Freq: H, dtype: float64
2.10 分类数据

这一部分介绍了 Pandas 中的分类数据类型(Categorical data type)。分类数据类型可以用来表示类别变量,它包含有限数量的可能值。在 Pandas 中,你可以使用 pd.Categorical 来创建一个分类变量。

df = pd.DataFrame(
        {"id": [1, 2, 3, 4, 5, 6], "raw_grade": ["a", "b", "b", "a", "a", "e"]}
   )
df
idraw_grade
01a
12b
23b
34a
45a
56e

将原始成绩转换为分类数据类型:

df["grade"] = df["raw_grade"].astype("category")

df["grade"]
0    a
1    b
2    b
3    a
4    a
5    e
Name: grade, dtype: category
Categories (3, object): ['a', 'b', 'e']

将类别重命名为更有意义的名称:

new_categories = ["very good", "good", "very bad"]

df["grade"] = df["grade"].cat.rename_categories(new_categories)
df["grade"]
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, dtype: category
Categories (3, object): ['very good', 'good', 'very bad']

对类别重新排序并同时添加缺少的类别(默认情况下,Series.cat() 下的方法返回一个新的 Series):

df["grade"] = df["grade"].cat.set_categories(
        ["very bad", "bad", "medium", "good", "very good"]
    )

df['grade']
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, dtype: category
Categories (5, object): ['very bad', 'bad', 'medium', 'good', 'very good']

排序是按类别中的顺序排序,而不是按词法顺序排序:

df.sort_values(by="grade")
idraw_gradegrade
56every bad
12bgood
23bgood
01avery good
34avery good
45avery good

按类型分组还会显示空类别:

df.groupby("grade").size()
grade
very bad     1
bad          0
medium       0
good         2
very good    3
dtype: int64
2.11 绘图

请参阅绘图文档(https://pandas.pydata.org/docs/user_guide/visualization.html#visualization)。

我们使用标准约定来引用 matplotlib API:

import matplotlib.pyplot as plt

plt.close("all")  # plt.close 方法用于关闭图形窗口:
ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))

ts = ts.cumsum()

ts.plot()
<AxesSubplot:>




<Figure size 640x480 with 1 Axes>

如果在 Jupyter Notebook 下运行,则绘图将显示在 plot() 上。否则,请使用 matplotlib.pyplot.show() 显示它,或使用 matplotlib.pyplot.savefig 将其写入文件。

plt.show()

在 DataFrame 上,plot() 方法可以方便地使用标签绘制所有列:

df = pd.DataFrame(
       np.random.randn(1000, 4), index=ts.index, columns=["A", "B", "C", "D"]
) 

df = df.cumsum()

plt.figure()

df.plot()

plt.legend(loc='best')
<matplotlib.legend.Legend at 0x7fea5088fc10>




<Figure size 640x480 with 0 Axes>



<Figure size 640x480 with 1 Axes>
2.12 读取与导出数据

CSV 文件

df.to_csv("foo.csv")  # 写入 csv 文件:使用 DataFrame.to_csv()
pd.read_csv("foo.csv")  # 从 csv 文件读取:使用 read_csv()
Unnamed: 0ABCD
02000-01-012.257795-1.077276-2.428040-0.873786
12000-01-022.901576-1.730733-2.182896-1.249288
22000-01-033.977965-2.370467-1.208194-0.218163
32000-01-044.211439-3.445451-2.245164-1.816434
42000-01-055.175889-3.970042-1.987473-1.450798
..................
9952002-09-22-15.295596-1.2376248.237827-18.912241
9962002-09-23-14.486983-1.0804289.215596-18.097333
9972002-09-24-15.461451-1.3037218.642622-16.890929
9982002-09-25-14.929007-1.3755809.116000-16.790838
9992002-09-26-14.999034-0.76459110.325462-15.971727

1000 rows × 5 columns

Excel 文件

df.to_excel("foo.xlsx", sheet_name="Sheet1")  # 使用 DataFrame.to_excel() 写入 excel 文件
pd.read_excel("foo.xlsx", "Sheet1", index_col=None, na_values=["NA"])  # 使用 read_excel() 从 excel 文件中读取
Unnamed: 0ABCD
02000-01-012.257795-1.077276-2.428040-0.873786
12000-01-022.901576-1.730733-2.182896-1.249288
22000-01-033.977965-2.370467-1.208194-0.218163
32000-01-044.211439-3.445451-2.245164-1.816434
42000-01-055.175889-3.970042-1.987473-1.450798
..................
9952002-09-22-15.295596-1.2376248.237827-18.912241
9962002-09-23-14.486983-1.0804289.215596-18.097333
9972002-09-24-15.461451-1.3037218.642622-16.890929
9982002-09-25-14.929007-1.3755809.116000-16.790838
9992002-09-26-14.999034-0.76459110.325462-15.971727

1000 rows × 5 columns

# 所有程序运行完毕,删除临时文件和文件夹
import os

os.remove('foo.xlsx')
os.remove('foo.csv')

总结

在本教程中,您学习了在 Pandas 的一些基础方法。

具体而言,您了解到:

  • 使用 Pandas 创建、读取或导出数据
  • 查看或选择数据,对数据进行处理(选择,删除,分组,分类等)
  • 表格处理,例如多表合并,改变表的数据结构
  • 使用 Pandas 时间序列数据
  • 结合 matplotlib 对 Pandas 数据进行绘图

你有什么问题吗? 欢迎与我们联系 bohrium@dp.tech

进一步阅读

如果您希望更深入学习 Pandas 及 Python 数据分析,本节提供有关该主题的更多资源。

书籍

Pandas 项目

参考

  1. https://pandas.pydata.org/docs/user_guide/10min.html#min
  2. https://pandas.pydata.org
  3. https://amzn.to/3DyLaJc
  4. https://github.com/pandas-dev/pandas

在线调试运行

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值