import pandas as pd
from pandas import Series, DataFrameData Analytics Introduction - Part 2
pandas 所包含的数据结构和数据处理工具的设计使得在 Python 中进行数据清洗和分析非常便捷。尽管 pandas 采用了很多 NumPy 的代码风格,但最大的不同在于 pandas 是用来处理表格型或异质类型数据的,而 NumPy 则相反,它更适合处理同质类型的数据。
在后续内容中,我们会使用如下的快捷方式导入 pandas:
pandas 中的两个常用的工具数据结构:Series 和 DataFrame 可以为大多数应用提供一个有效易用的基础。
Series 是一种一维的数据型对象,它包含了一个值序列(与 NumPy 中的类型相似),并且包含了数据标签,称之为索引(index),最简单的序列可以仅由一个数组构成:
交互式环境中 Series 的表示左边为索引,右边为值。由于我们不为数据指定索引,默认生成的索引是从 0 到 N-1(N 是数据的长度)。可以通过 values 属性和 index 属性分别获取 Series 对象的值和索引。
Series 可以被看做是一个长度固定且有序的字典,因为它将索引值和数据值按位置配对。
可以使用字典生成一个 Series:
因为 California 没有出现在 d 的键中,它对应的值是 NaN(Not a Number),是 pandas 中用于标记缺失值的方式。因为 Utah 不在 d 中,它被排除在结果外。
pandas 使用 isnull 和 notnull 函数检查缺失值:
isnull 和 notnull 也是 Series 实例方法。
DataFrame 表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame 既有行索引也有列索引,它可以被视为一个共享相同索引的 Series 的字典。在 DataFrame 中,数据被存储为一个以上的二维块,而不是列表、字典或其他一维数组的结合。
有多种方式可以构建 DataFrame,其中最常用的方式是利用包含等长度列表或 NumPy 数组的字典来构建 DataFrame:
对于大型 DataFrame,head 方法会选出头部的 n 行:
DataFrame 可以按照指定列的顺序排序:
当将列表或数组赋值给一个列时,值的长度必须和 DataFrame 匹配。如果将 Series 赋值给一列时,Series 的索引将会按照 DataFrame 的索引重新排序,并在空缺的地方填充缺失值:
可以用嵌套字典生成 DataFrame:
Neveda Ohio
2001 2.4 1.7
2002 2.9 3.6
2000 NaN 1.5
可以使用类似 NumPy 的方法对 DataFrame 进行转置:
pandas 中的索引对象是用于储存轴标签和其他元数据的(例如:轴名称或标签),在构造 Series 或 DataFrame 时,所使用的任意数组或标签序列都可以在内部转换为索引对象。
Index(['a', 'b', 'c'], dtype='object')
| 方法 | 描述 | 方法 | 描述 |
|---|---|---|---|
append |
将额外的索引对象粘贴到原索引后, 产生一个新的索引 |
difference |
计算两个索引的差集 |
intersection |
计算两个索引的交集 | union |
计算两个索引的并集 |
isin |
计算表示每一个值是否在传值容器 中的布尔数组 |
delete |
将位置 i 的元素删除,并产生新的索引 |
drop |
根据传参删除指定索引值, 并产生新的索引 |
insert |
在位置 i 插入元素,并产生新的索引 |
is_monotonic |
如果索引序列递增则返回 True |
is_unique |
如果索引序列唯一则返回 True |
unique |
计算索引的唯一值序列 |
reindex 用于创建一个符合新索引的新对象:
在 DataFrame 中,reindex 可以改变行索引,列索引,也可以同时改变二者。当仅传入一个序列时,结果中的行会重建索引,列可以使用 columns 关键字重建索引。
Ohio Texas California
a 0.0 1.0 2.0
b 3.0 4.0 5.0
c 6.0 7.0 8.0
d NaN NaN NaN
reindex 方法的参数详见下表:
| 参数 | 描述 |
|---|---|
index |
新建作为索引的序列,可以是索引示例或任意其他序列型 Python 数据结构,索引使用时无需复制 |
method |
插值方法,ffill 为向前填充,bfill 为向后填充 |
fill_value |
通过重新索引引入缺失数据时使用的替代值 |
limit |
当前向或后向填充时,所需填充的最大尺寸间隔 |
tolerance |
当前向或后向填充时,所需填充的不精确匹配下的最大尺寸间隔 |
level |
匹配 MultiIndex 级别的简单索引 |
copy |
如果为 True,即使新索引等于旧索引,也总是复制底层数据 |
drop 方法返回含有指示值或轴向上删除值的新对象:
drop 会根据行标签删除值(轴 0):
可以通过传递 axis=1 或 axis='columns' 删除列:
使用单个值或序列,可以从 DataFrame 中索引出一个或多个列:
可以根据一个布尔值数组切片或选择数据:
使用 loc 和 iloc 可以对 DataFrame 在行上的标签索引,轴标签(loc)或整数标签(iloc)以 NumPy 风格的语法从 DataFrame 中选出数组的行和列的子集。
| 类型 | 描述 |
|---|---|
df[val] |
从 DataFrame 中选择单列或列序列;特殊情况的便利:布尔数组(过滤行), 切片(切片行)或布尔值 DataFrame(根据某些标准设置的值) |
df.loc[val] |
根据标签选择 DataFrame 的单行或多行 |
df.loc[:, val] |
根据标签选择单列或多列 |
df.loc[val1, val2] |
同时选择行和列的一部分 |
df.iloc[where] |
根据整数位置选择单行或多行 |
df.iloc[:, where] |
根据整数位置选择单列或多列 |
df.iloc[where_i, where_j] |
根据整数位置选择行和列 |
df.at[label_i, label_j] |
根据行、列标签选择单个标量值 |
df.iat[i, j] |
根据行、列整数位置选择单个标量值 |
不同索引对象之间的算术行为是 pandas 提供的一项重要特性,将对象相加时,如果存在某个索引对不同,则返回结果的索引将是索引对的并集。
在 DataFrame 中,行和列上都会执行对齐:
在 df1 上使用 add 方法,我们将 df2 和一个 fill_value 作为参数传入:
b c d e
Colorado 6.0 7.0 8.0 NaN
Ohio 3.0 1.0 6.0 5.0
Oregon 9.0 NaN 10.0 11.0
Texas 9.0 4.0 12.0 8.0
Utah 0.0 NaN 1.0 2.0
每个方法都有一个以 r 开头的副本,副本方法的参数是翻转的,例如:1 / df1 和 df1.rdiv(1) 是等价的。
| 方法 | 描述 |
|---|---|
add, radd |
加法(+) |
sub, rsub |
减法(-) |
div, rdiv |
除法(/) |
floordiv, rfloordiv |
整除(//) |
mul, rmul |
乘法(*) |
pow, rpow |
幂次方(**) |
DataFrame 和 Series 间的算数操作与 NumPy 中不同维度数组间的操作类似。
NumPy 的通用函数(逐元素数组方法)对 pandas 对象也有效:
通过传递 axis='columns' 给 apply 函数,函数会被每行调用一次:
Utah 0.414531
Ohio 4.425821
Texas 3.077857
Oregon 2.403221
dtype: float64
逐元素的 Python 函数也可以,例如对 df 中的每个值计算一个格式化的字符串,可以使用 applymap 方法:
b d e
Utah -0.752446 -0.709925 -0.337916
Ohio 0.726541 2.137040 -2.288782
Texas 0.674664 -0.896596 2.181261
Oregon 0.885203 -1.067982 -1.518018
使用 applymap 作为函数名是因为 Series 有 map 方法,可以将一个逐元素的函数应用到 Series 上:
如需按照行或列索引进行字典型排序,需要使用 sort_index 方法,其返回一个新的、排序好的对象:
在 DataFrame 中,可以在各个轴上按索引排序:
对 DataFrame 排序时,可以使用一列或多列作为排序键,通过设置 sort_values 的参数 by 实现:
DataFrame 可以对行或列计算排名:
在排名中打破评级关系的方法如下:
| 方法 | 描述 |
|---|---|
average |
默认:在每个组中分配平均排名 |
min |
对整个组使用最小排名 |
max |
对整个组使用最大排名 |
first |
按照值在数据中出现的次序分配排名 |
dense |
类似 min,但排名总是增加 1 而非组元素数量 |
pandas 装配了一个常用数学、统计学方法的集合,与 NumPy 中类似方法相比,其内建了处理缺失值的功能。
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
调用 sum 方法返回一个包含列上加和的 Series:
idmax 和 idmin 返回的是间接统计信息,除了归约方法外,有的方法是积累型方法:
还有一类方法不是归约型方法也不是积累型方法,describe 即其中之一,它一次性产生多个汇总统计:
one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000
对于非数值类型数据,则产生另一种汇总统计:
| 方法 | 描述 | 方法 | 描述 |
|---|---|---|---|
count |
非 NA 值个数 | describe |
各列汇总值 |
min, max |
计算最小/大值 | argmin, argmax |
计算最小/大值的索引位置 |
idxmin, idmax |
计算最小/大值的索引标签 | quantile |
计算样本的分位数 |
sum |
加和 | mean |
均值 |
median |
中位数 | mad |
平均值的平均绝对偏差 |
prod |
连乘 | var, std |
样本方差/标准差 |
skew, kurt |
偏度/峰度 | cumsum |
累加 |
cummin, cummax |
累积值的最小/大值 | cumprod |
累积 |
diff |
计算第一个算术差值 | pct_change |
计算百分比 |
Series 的 corr 计算的是两个 Series 中的重叠的,非 NA 的,按索引对齐的值的相关性,cov 计算协方差:
DataFrame 的 corrwith 方法可以计算出 DataFrame 行或列与另一个序列或 DataFrame 的相关性。当传入一个 Series 时,会返回一个含有为每列计算相关性值的 Series:
unique 函数可以给出 Series 中的唯一值:
array(['c', 'a', 'd', 'b'], dtype=object)
sort 方法可以对其进行排序,value_counts 可以计算 Series 包含的值的个数:
isin 执行向量化的成员属性检查,还可以将数据集以 Series 或 DataFrame 一列的形式过滤为数据集的值子集:
将表格型数据读取为 DataFrame 对象是 pandas 的重要特性,下表为常用的数据读取函数:
| 函数 | 描述 |
|---|---|
read_csv |
从文件、URL 或文件型对象读取分隔好的数据,默认分隔符为 , |
read_table |
从文件、URL 或文件型对象读取分隔符的数据,默认分隔符为 \t |
read_fwf |
从特定宽度格式的文件中读取数据(无分隔符) |
read_clipboard |
read_table 的剪切板版本 |
read_excel |
从 Excel 的 XLS 或 XLSX 文件中读取表格数据 |
read_hdf |
读取用 pandas 存储的 HDF5 文件 |
read_html |
从 HTML 文件中读取所有表格数据 |
| 函数 | 描述 |
|---|---|
read_json |
从 JSON 字符串中读取数据 |
read_msgpack |
读取 MessagePackage 二进制格式的 pandas 数据 |
read_pickle |
读取以 Python pickle 格式存储的任意对象 |
read_sas |
读取存储在 SAS 系统中定制存储格式的 SAS 数据集 |
read_sql |
将 SQL 查询的结果读取为 pandas 的 DataFrame |
read_stata |
读取 Stata 格式的数据集 |
read_feather |
读取 Feather 二进制格式 |
read_csv / read_table 的函数参数如下表所示:
| 参数 | 描述 |
|---|---|
path |
表明文件系统位置的字符串,URL 或文件型对象 |
sep, delimiter |
用于分割每行字段的字符序列或正则表达式 |
header |
用作列名的行号,默认是 0,如果没有列名则为 None |
index_col |
用作结果中行索引的列号或列名,可以是一个单一的名称/数字,也可以是一个分层索引 |
names |
结果的列名列表,和 header=None 一起用 |
skiprows |
从文件开头处起,需要跳过的行数或行号列表 |
comment |
在行结尾处分隔注释的字符 |
| 参数 | 描述 |
|---|---|
parse_dates |
尝试将数据解析为 datetime,默认是 False,如果为 True,将尝试解析所有的列。也可以指定列号或列名列表来进行解析。如果列表的元素是元组或列表,将会把多个列组合在一起进行解析(例如:日期/时间将拆分为两列) |
keep_date_col |
如果连接列到解析日期上,保留被连接的列,默认是 False |
converters |
包含列名称映射到函数的字典(例如:{'foo': f} 会把函数 f 应用到 foo 列 |
dayfirst |
解析非明确日期时,按照国际格式处理(例如:7/6/2012 -> June 7, 2012),默认为 False |
date_parser |
用于解析日期的函数 |
| 参数 | 描述 |
|---|---|
nrows |
从文件开头处理读入的行数 |
iterator |
返回一个 TextParser 对象,用于零散地读入文件 |
chunksize |
用于迭代的块大小 |
skip_footer |
忽略文件尾部的行数 |
verbose |
打印各种解析器输出的信息,比如位于非数值列中的缺失值数量 |
encoding |
Unicode 文本编码(例如:utf-8 用于表示 UTF-8 编码的文本) |
squeeze |
如果解析数据只包含一列,返回一个 Series |
thousands |
千位分隔符(例如:, 或 .) |
使用 DataFrame 的 to_csv 方法,可以将数据导出为逗号分隔符文件:
通过 sep 可是设置分隔符:
| 参数 | 描述 |
|---|---|
delimiter |
一般用于分隔字段的字符,默认是 , |
lineterminator |
行终止符,默认是 \r\n,读取器会忽略行终止符并识别跨平台行终止符 |
quotechar |
用在含有特殊字符字段中的引号,默认是 " |
quoting |
引用惯例。选项包括 csv.QUOTE_ALL(引用所有的字段),csv.QUOTE_MINIMAL(只是用特殊字符,如分隔符),csv.QUOTE_NONMUERIC 和 csv.QUOTE_NONE(不引用),默认为 QUOTE_MINIMAL。 |
skipinitialspace |
忽略每个分隔符后的空白,默认是 False |
doublequote |
如何处理字段内部的引号,如果为 True,则是双引号 |
escapechar |
当引用设置为 csv.QUOTE_NONE 时用于转义分隔符的字符串,默认是禁用的 |
JSON(JavaScript Object Notation)是一种常用的数据格式,其基本类型包括:对象(字典)、数组(列表)、字符串、数字、布尔值和空值,对象中的所有键必须是字符串。在 Python 中可以利用内建的 json 模块处理 JSON。
利用 json.loads 可以将 JSON 字符串转换为 Python 对象:
{'name': 'Wes',
'place_lived': ['United States', 'Spain', 'Germany'],
'pet': None,
'siblings': [{'name': 'Scott', 'age': 30, 'pets': ['Zeus', 'Zuko']},
{'name': 'Katie', 'age': 38, 'pets': ['Sixes', 'Stache', 'Cisco']}]}
利用 json.dumps 可以将 Python 对象装换回 JSON 字符串。
pandas.read_json 可以自动将 JSON 数据集按照指定次序转换为 Series 或 DataFrame,example.json 数据内容如下:
同样,从 pandas 数据中导出 JSON 可以使用 Series 和 DataFrame 的 to_json 方法。
使用 Python 内建的 pickle 序列化模块进行二进制格式操作是存储数据(序列化)最高效,最方便的方法之一。pandas 对象拥有 to_pickle 方法可以将数据以 pickle 格式写入文件。使用 read_pickle 可以方便的读入 pickle 序列化后的文件。
HDF5 是一个备受好评的文件格式,用于存储大量的科学数组数据。每个 HDF5 文件可以存储多个数据集并支持元数据,与更简单的格式相比,HDF5 支持多种压缩模式的即时压缩,使得重复模式的数据可以更高效地存储。HDF5 适用于处理不适合在内存中存储的超大型数据,可以使你高效读写大型数组的一小块。
pandas 提供一个高阶的接口,可以简化 Series 和 DataFrame 的存储。HDFStore 类像字典一样工作并处理低级别细节:
to_hdf 和 read_hdf 函数提供了便捷的操作方法。
分层索引是 pandas 的重要特性,允许在一个轴向上拥有多个索引层级。分层索引提供了一种在更低维度的形式中处理更高维度数据的方式。
分层索引在重塑数据和数组透视表等分组操作中扮演重要角色,例如:使用 unstack 方法将数据在 DataFrame 中重新排列:
1 2 3
a 0.637485 0.208254 0.073895
b -1.206255 NaN 1.515729
c -0.290793 0.378494 NaN
d NaN 0.465555 -0.787307
unstack 的反操作是 stack
分层的层级可以有名称(可以是字符串或 Python 对象),如果层级有名称,这些名称会在控制台中显示:
有时需要重新排列轴上的层级顺序,或者按照特定层级的值对数据进行排序。swaplevel 接受两个层级序号或层级名称,返回一个进行了层级变更的新对象:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11
sort_index 只能在单一层级上对数据进行排序,在进行层级变换时,使用 sort_index 以使得结果按照层级进行字典排序:
DataFrame 的 set_index 会生成一个新的 DataFrame,新的 DataFrame 使用一个或多个列作为索引:
合并或连接操作通过一个或多个键来联合数据集,这些操作是关系型数据库的核心内容。pandas 中的 merge 函数主要用于将各种 join 操作应用到数据上:
可以显式地指定连接键:
如果对象的列名是不同的,可以分别为他们指定列名:
key1 key2 lval rval
0 bar one 3.0 6.0
1 bar two NaN 7.0
2 foo one 1.0 4.0
3 foo one 1.0 5.0
4 foo two 2.0 NaN
key1 key2_x lval key2_y rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo two 2 one 4
3 foo two 2 one 5
4 bar one 3 one 6
5 bar one 3 two 7
merge 函数的参数如下表所示:
| 参数 | 描述 |
|---|---|
left |
合并时操作中左边的 DataFrame |
right |
合并时操作中右边的 DataFrame |
how |
inner, outer, left, right 之一,默认为 inner |
on |
需要连接的列名,需要在两边的 DataFrame 中都存在。 |
left_on |
左 DataFrame 中用作连接的键 |
right_on |
右 DataFrame 中用作连接的键 |
merge 函数的参数如下表所示:
| 参数 | 描述 |
|---|---|
left_index |
使用 left 的行索引作为它的连接键(如果是 MultiIndex,则为多个键) |
right_index |
使用 right 的行索引作为它的连接键(如果是 MultiIndex,则为多个键) |
sort |
通过连接键按字母顺序对合并的数据进行排序,默认为 True |
suffixes |
在重叠情况下,添加到列名后的字符串元组,默认为 ('_x', '_y') |
copy |
如果为 False,则在某些特殊情况下避免将数据复制到结果数据结构中,默认情况下总是复制 |
indicator |
添加一个特殊的列 _merge,指示每一行的来源。值将根据每行中连接数据的来源分别为 left_only, right_only, both |
DataFrame 有一个方便的 join 实例方法,用于按照索引合并。该方法也可以用于合并多个索引相同或相似但没有重叠列的 DataFrame 对象:
Ohio Nevada Missouri Alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
可以向 join 方法传递一个 DataFrame 列表:
Ohio Nevada Missouri Alabama New York
a 1.0 2.0 NaN NaN 7.0
c 3.0 4.0 9.0 10.0 8.0
e 5.0 6.0 13.0 14.0 9.0
b NaN NaN 7.0 8.0 NaN
d NaN NaN 11.0 12.0 NaN
f NaN NaN NaN NaN 10.0
另一种数据组合操作可互换地称为拼接、绑定或堆叠。NumPy 的 concatenate 函数可以在 NumPy 数组上实现该该功能:
在 Series 和 DataFrame 等 pandas 对象上下文中,使用标记的轴可以进一步泛化数据连接。尤其是你还有需要考虑的事情:
pandas 的 concat 函数提供了一种一致性的方式来解决以上问题。
调用 concat 方法会将值和索引连在一起:
拼接在一起的各部分无法在结果中区分是一个潜在的问题。假设你想在连接轴向上创建一个多层索引,可以使用 keys 参数来实现:
对于 DataFrame 对象:
| 参数 | 描述 |
|---|---|
objs |
需要连接的 pandas 对象列表或字典 |
axis |
连接的轴向,默认是 0(沿着行方向) |
join |
用于指定连接方式(inner 或 outer) |
keys |
与要连接的对象关联的值,沿着连接轴形成分层索引。 |
levels |
在键值传递时,该参数用于指定多层索引的层级 |
names |
传入 keys 或 levels 时用于多层索引的层级名称 |
verify_integrity |
检查连接对象中的新轴是否重复,如果是,则发生异常,默认为 False |
ignore_index |
不沿着连接轴保留索引,而产生一段新的索引 |
另一种数据联合场景,既不是合并,也不是连接。两个数据集的索引全部或部分重叠,考虑 NumPy 的 where 函数,这个函数可以进行面向数组的 if-else 等价操作:
在 DataFrame 中,combine_first 逐列进行相同的操作,可以理解为利用传入的数值替换对象的缺失值:
多层索引在 DataFrame 中提供了一种一致性方式用于重排列数据,包含两个基础操作:
stack(堆叠),“旋转”或将列中的数据透视到行unstack(拆堆),将行中的数据透视到列如果层级中的所有值并未包含于每个子分组中,拆分可能会引入缺失值:
在 DataFrame 中拆堆时,被拆堆的层级会变为结果中最低的层级:
side left right
state num
Ohio one 0 5
two 1 6
three 2 7
Colorado one 3 8
two 4 9
three 5 10
调用 stack 方法时,可以指明需要堆叠的轴向名称:
从一个多层索引序列中,可以使用 unstack 方法将数据重排列后放入一个 DataFrame 中:
默认情况下,最内层是已拆堆的(与 stack 方法一样),传入层级序号或名称来拆分一个不同的层级:
DataFrame 中的 pivot 和 melt 方法提供了将数据“由长到宽”和“由宽到长”变换的支持。
版权所有 © 范叶亮 Leo Van