第四章:使用 pandas 进行数据操作和分析
在本章中,您将学习基于 NumPy 构建的 Python pandas
库,该库为结构化数据框提供了数据操作和分析方法。根据维基百科对 pandas 的页面,pandas 这个名字是从 panel data 派生而来,它是一个描述多维结构化数据集的计量经济学术语。
pandas
库包含两种基本数据结构来表示和操作带有各种索引选项的结构化矩形数据集:Series 和 DataFrames。两者都使用索引数据结构。
Python 中处理金融数据的大多数操作都是基于 DataFrames 的。DataFrame 就像一个 Excel 工作表 - 一个可能包含多个时间序列的二维表格,存储在列中。因此,我们建议您在您的环境中执行本章中的所有示例,以熟悉语法并更好地了解可能的操作。
在本章中,我们将涵盖以下主题:
- 介绍 pandas Series、pandas DataFrames 和 pandas Indexes
- 学习 pandas DataFrames 上的基本操作
- 使用 pandas DataFrames 探索文件操作
技术要求
本章中使用的 Python 代码在书籍代码存储库中的Chapter04/pandas.ipynb
笔记本中可用。
介绍 pandas Series、pandas DataFrames 和 pandas Indexes
pandas Series、pandas DataFrames 和 pandas Indexes 是 pandas 的基本数据结构。
pandas.Series
pandas.Series
数据结构表示同质值(整数值、字符串值、双精度值等)的一维系列。 Series 是一种列表类型,只能包含带索引的单个列表。另一方面,Data Frame 是一个包含一个或多个 series 的集合。
让我们创建一个pandas.Series
数据结构:
import pandas as pd ser1 = pd.Series(range(1, 6)); ser1
该系列包含在第一列中的索引,第二列中的索引对应的值:
0 1 1 2 2 3 3 4 4 5 dtype: int64
我们可以通过指定index
参数来指定自定义索引名称:
ser2 = pd.Series(range(1, 6), index=['a', 'b', 'c', 'd', 'e']); ser2
输出将如下所示:
a 1 b 2 c 3 d 4 e 5 dtype: int64
我们还可以通过字典指定index -> value
映射来创建一个系列:
ser3 = pd.Series({ 'a': 1.0, 'b': 2.0, 'c': 3.0, 'd': 4.0, 'e': 5.0 }); ser3
输出如下所示:
a 1.0 b 2.0 c 3.0 d 4.0 e 5.0 dtype: float64
pandas.Series.index
属性允许我们访问索引:
ser3.index
索引的类型是pandas.Index
:
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
可以使用pandas.Series.values
属性访问系列的值:
ser3.values
值如下:
array([ 1., 2., 3., 4., 5.])
我们可以通过修改pandas.Series.name
属性为系列指定一个名称:
ser3.name = 'Alphanumeric'; ser3
输出如下所示:
a 1.0 b 2.0 c 3.0 d 4.0 e 5.0 Name: Alphanumeric, dtype: float64
上述示例演示了构建 pandas Series 的多种方式。让我们了解一下 DataFrame,这是一种可能包含多个 Series 的数据结构。
pandas.DataFrame
pandas.DataFrame
数据结构是多个可能不同类型的pandas.Series
对象的集合,由相同的公共 Index 对象索引。
所有统计时间序列操作的大部分都是在数据框上执行的,pandas.DataFrame
针对数据框的并行超快处理进行了优化,比在单独系列上进行处理快得多。
我们可以从字典创建一个数据框,其中键是列名,该键的值包含相应系列/列的数据:
df1 = pd.DataFrame({'A': range(1,5,1), 'B': range(10,50,10), 'C': range(100, 500, 100)}); df1
输出如下所示:
A B C 0 1 10 100 1 2 20 200 2 3 30 300 3 4 40 400
我们也可以在这里传递index=
参数来标记索引:
df2 = pd.DataFrame({'A': range(1,5,1), 'B': range(10,50,10), 'C': range(100, 500, 100)}, index=['a', 'b', 'c', 'd']); df2
这构建了以下数据框:
A B C a 1 10 100 b 2 20 200 c 3 30 300 d 4 40 400
pandas.DataFrame.columns
属性返回不同列的名称:
df2.columns
结果是一个Index
对象:
Index(['A', 'B', 'C'], dtype='object')
索引可以从pandas.DataFrame.index
属性中访问:
df2.index
这给了我们这个:
Index(['a', 'b', 'c', 'd'], dtype='object')
数据框还包含pandas.DataFrame.values
属性,该属性返回列中包含的值:
df2.values
结果是以下 2D 数组:
array([[ 1, 10, 100], [ 2, 20, 200], [ 3, 30, 300], [ 4, 40, 400]])
我们可以通过以下方式向数据框添加具有指定值和相同索引的新列:
df2['D'] = range(1000,5000,1000); df2
更新后的数据框如下:
A B C D a 1 10 100 1000 b 2 20 200 2000 c 3 30 300 3000 d 4 40 400 4000
我们可以为数据框的索引和列指定名称。
我们可以通过修改pandas.DataFrame.index.name
属性来命名索引:
df2.index.name = 'lowercase'; df2
这导致以下更新后的数据框:
A B C D lowercase a 1 10 100 1000 b 2 20 200 2000 c 3 30 300 3000 d 4 40 400 4000
可以使用pandas.DataFrame.columns.name
属性重命名列:
df2.columns.name = 'uppercase'; df2
新数据框如下所示:
uppercase A B C D lowercase a 1 10 100 1000 b 2 20 200 2000 c 3 30 300 3000 d 4 40 400 4000
前面的例子演示了如何构造数据框。
pandas.Index
pandas.Series
和pandas.DataFrame
数据结构都利用pandas.Index
数据结构。
有许多特殊类型的Index
对象:
Int64Index
:Int64Index
包含整数索引值。MultiIndex
:MultiIndex
包含用于分层索引的元组索引,我们将在本章中探讨。DatetimeIndex
:DatetimeIndex
,我们之前已经见过,包含时间序列数据集的日期时间索引值。
我们可以通过以下方式创建一个pandas.Index
对象:
ind2 = pd.Index(list(range(5))); ind2
结果是这样的:
Int64Index([0, 1, 2, 3, 4], dtype='int64')
注意
Index
对象是不可变的,因此无法就地修改。
让我们看看如果我们尝试修改Index
对象中的元素会发生什么:
ind2[0] = -1
我们得到以下输出:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-34-20c233f961b2> in <module>() ----> 1 ind2[0] = -1 ... TypeError: Index does not support mutable operations
Python 警告我们无法手动修改索引对象。
我们现在已经学会了如何构建系列和数据框。让我们探索对数据框进行的基本操作。
学习重要的 pandas.DataFrame 操作
本节描述了对数据框进行的基本操作。了解它们的存在以及如何使用它们将为您节省大量时间。
数据框的索引、选择和过滤
pandas 数据结构通过特殊的Index
对象进行索引(而numpy.ndarrays
和 Python 列表对象仅可通过整数索引)。本课程的步骤如下:
- 让我们检查在本章前面创建的
df2
数据框的内容:
df2
- 输出如下所示:
uppercase A B C D lowercase a 1 10 100 1000 b 2 20 200 2000 c 3 30 300 3000 d 4 40 400 4000
- 我们可以通过执行以下操作选择列
B
中的值序列:
df2['B']
- 这产生了以下序列:
lowercase a 10 b 20 c 30 d 40 Name: B, dtype: int64
- 我们可以通过传递列名列表来选择多个列(与我们在
numpy.ndarrays
中看到的有些相似):
df2[['A', 'C']]
- 这产生了以下具有两列的 DataFrame:
uppercase A C lowercase a 1 100 b 2 200 c 3 300 d 4 400
- 我们可以通过以下方式使用 DataFrame 进行布尔选择:
df2[(df2['D'] > 1000) & (df2['D'] <= 3000)]
- 这选择了满足提供条件的以下行:
uppercase A B C D lowercase b 2 20 200 2000 c 3 30 300 3000
pandas.DataFrame.loc[...]
属性允许我们索引行而不是列。以下选择了两行c
和d
:
df2.loc[['c', 'd']]
- 这产生了以下子集 DataFrame:
uppercase A B C D lowercase c 3 30 300 3000 d 4 40 400 4000
- pandas DataFrame 仍然支持通过
pandas.DataFrame.iloc[...]
属性进行标准整数索引。我们可以通过这样做来选择第一行:
df2.iloc[[0]]
- 这选择了以下单行 DataFrame:
uppercase A B C D lowercase a 1 10 100 1000
- 我们可以通过类似这样的操作修改 DataFrame:
df2[df2['D'] == 2000] = 0; df2
- 这将 DataFrame 更新为这个新 DataFrame:
uppercase A B C D lowercase a 1 10 100 1000 b 0 0 0 0 c 3 30 300 3000 d 4 40 400 4000
在本节中,我们学习了如何索引、选择和过滤 DataFrame。在下一节中,我们将学习如何删除行和列。
从 DataFrame 中删除行和列
从 DataFrame 中删除行和列是一个关键操作——它不仅有助于节省计算机的内存,还确保 DataFrame 只包含逻辑上需要的信息。步骤如下:
- 让我们显示当前 DataFrame:
df2
- 此 DataFrame 包含以下内容:
uppercase A B C D lowercase a 1 10 100 1000 b 0 0 0 0 c 3 30 300 3000 d 4 40 400 4000
- 要删除索引为
b
的行,我们使用pandas.DataFrame.drop(...)
方法:
df2.drop('b')
- 这产生了一个没有索引为
b
的行的新 DataFrame:
uppercase A B C D lowercase a 1 10 100 1000 c 3 30 300 3000 d 4 40 400 4000
- 让我们检查原始 DataFrame 是否已更改:
df2
- 输出显示没有,也就是说,默认情况下
pandas.DataFrame.drop(...)
不是原位的:
uppercase A B C D lowercase a 1 10 100 1000 b 0 0 0 0 c 3 30 300 3000 d 4 40 400 4000
- 要修改原始 DataFrame,我们使用
inplace=
参数:
df2.drop('b', inplace=True); df2
- 新的原地修改的 DataFrame 如下所示:
uppercase A B C D lowercase a 1 10 100 1000 c 3 30 300 3000 d 4 40 400 4000
- 我们也可以删除多个行:
df2.drop(['a', 'd'])
- 这返回了以下新 DataFrame:
uppercase A B C D lowercase c 3 30 300 3000
- 要删除列而不是行,我们指定额外的
axis=
参数:
df2.drop(['A', 'B'], axis=1)
- 这给了我们具有两个删除列的新 DataFrame:
uppercase C D lowercase a 100 1000 c 300 3000 d 400 4000
我们在本节中学习了如何删除行和列。在下一节中,我们将学习如何对值进行排序和 rand。
Python 金融交易实用指南(二)(2)https://developer.aliyun.com/article/1523757