Python 常用模块系列:
- [Python] 常用模块(1):内建模块 – random & datetime
- [Python] 常用模块(2):内建模块 – re 以及正则表达式
- [Python] 常用模块(3):内建模块 – math & itertools
- [Python] 常用模块(4):NumPy 上
- [Python] 常用模块(4):NumPy 中
- [Python] 常用模块(4):NumPy 下
- [Python] 常用模块(5):pandas 1
- [Python] 常用模块(5):pandas 2
- [Python] 常用模块(5):pandas 3
- [Python] 常用模块(5):pandas 4
- [Python] 常用模块(5):pandas 5
- [Python] 常用模块(5):pandas 6
- [Python] 常用模块(5):pandas 7(本文)
- [Python] 常用模块(5):pandas 8
- [Python] 常用模块(5):pandas 9
文章目录
老规矩,先建立两个数据框。
>>> df1 = pd.DataFrame({"a":np.random.randn(4),
... "b":[1, 3, 5, 7]},
... index = ["A", "B", "C", "D"])
>>> print(df1)
a b
A 1.624345 1
B -0.611756 3
C -0.528172 5
D -1.072969 7
>>> df2 = pd.DataFrame({"a":np.random.randint(4),
... "c":[1, 2, 4, 5]},
... index = ["A", "C", "D", "F"])
>>> print(df2)
a c
A 2 1
C 2 2
D 2 4
F 2 5
数据框的合并
首先要讲一下两种合并方式:inner join 和 outer join。图片来自 《R for Data Science》 第 13 章。假设我们希望合并如下两个数据框:
左侧的数字是索引,右侧的数值是值。合并数据框根据索引的值,合并索引一致的值,根据合并的方法不同对索引值不同的数据进行不同的处理。
- inner join:
只合并索引值相同的值,索引值不同的值会被丢弃。
如图,两个数据框中索引为 1 和 2 的值合并,索引为 3 和 4 的值被丢弃。 - outer join
outer join 保留了索引不同的值,根据保留方式的不同分为 left,right 和 full 三种。
- left join 保留了所有左侧的值;右侧有、左侧没有的值被丢弃,左侧有、右侧没有的值在右侧被标记成 “NA”。
- right join 则相反,保留所有右侧的值;右侧有、左侧没有的值在左侧被标记成 “NA”,左侧有、右侧没有的值在右侧被丢弃。
- full join 保留了两侧单独存在的值,在缺失值处标记 “NA” (Python 里仍然称为 outer join)。
数据框的拼接:pd.concat(objs, axis=0, join=“outer”, ignore_index=False, keys=None)
我们先来看一下最基本的情况:仅适用参数 objs
。
>>> print(pd.concat([df1, df2]))
a b c
A 1.624345 1.0 NaN
B -0.611756 3.0 NaN
C -0.528172 5.0 NaN
D -1.072969 7.0 NaN
A 2.000000 NaN 1.0
C 2.000000 NaN 2.0
D 2.000000 NaN 4.0
F 2.000000 NaN 5.0
因为默认使用 outer join(确切地说使用了 full join),缺失值被命名为 NaN
。拼接以后保留了原来的索引,重置可以使用 ignore_index=True
参数。
>>> print(pd.concat([df1, df2], ignore_index=True))
a b c
0 1.624345 1.0 NaN
1 -0.611756 3.0 NaN
2 -0.528172 5.0 NaN
3 -1.072969 7.0 NaN
4 2.000000 NaN 1.0
5 2.000000 NaN 2.0
6 2.000000 NaN 4.0
7 2.000000 NaN 5.0
也可以为原来的数据框分别设置一级索引。
>>> print(pd.concat([df1, df2], keys=["from left", "from right"]))
a b c
from left A 1.624345 1.0 NaN
B -0.611756 3.0 NaN
C -0.528172 5.0 NaN
D -1.072969 7.0 NaN
from right A 2.000000 NaN 1.0
C 2.000000 NaN 2.0
D 2.000000 NaN 4.0
F 2.000000 NaN 5.0
当然也可以改变拼接的轴。
>>> print(pd.concat([df1, df2], axis=1))
a b a c
A 1.624345 1.0 2.0 1.0
B -0.611756 3.0 NaN NaN
C -0.528172 5.0 2.0 2.0
D -1.072969 7.0 2.0 4.0
F NaN NaN 2.0 5.0
也可以合并方法。
>>> print(pd.concat([df1, df2], join="inner"))
a
A 1.624345
B -0.611756
C -0.528172
D -1.072969
A 2.000000
C 2.000000
D 2.000000
F 2.000000
数据框的合并:
这里要用到 merge
函数,它可以用作一个函数 pd.merge
也可以用作一个方法 df.merge
。
- 用作一个函数:pd.merge(left, right, how=“inner”, on=None, left_on=None, right_on=None, suffixes=("_x", “_y”))
- 这里的合并专指两个数据框的纵向合并(即合并行)。
left
和right
分别对应了合并的两个数据框,how
定义了合并方法,如果没有指定连接键on
,系统默认使用两个数据框中相同的列做定位。这样是基于行的合并。
>>> print(pd.merge(df1, df2, how="outer"))
a b c
0 1.624345 1.0 NaN
1 -0.611756 3.0 NaN
2 -0.528172 5.0 NaN
3 -1.072969 7.0 NaN
4 2.000000 NaN 1.0
5 2.000000 NaN 2.0
6 2.000000 NaN 4.0
7 2.000000 NaN 5.0
- 可以使用
left_on
和right_on
手动指定合并的定位列,这样是基于列的合并。
>>> print(pd.merge(df1, df2, how="outer", left_on="b", right_on="c"))
a_x b a_y c
0 1.624345 1.0 2.0 1.0
1 -0.611756 3.0 NaN NaN
2 -0.528172 5.0 2.0 5.0
3 -1.072969 7.0 NaN NaN
4 NaN NaN 2.0 2.0
5 NaN NaN 2.0 4.0
- 无论是基于行的合并还是基于列的合并,原来的索引都会被重置。也可以用
suffixes
参数手动为重复的列添加后缀以区分不同的来源。
>>> print(pd.merge(df1, df2, how="outer", left_on="b", right_on="c", suffixes=["_left", "_right"]))
a_left b a_right c
0 1.624345 1.0 2.0 1.0
1 -0.611756 3.0 NaN NaN
2 -0.528172 5.0 2.0 5.0
3 -1.072969 7.0 NaN NaN
4 NaN NaN 2.0 2.0
5 NaN NaN 2.0 4.0
- 用作一个数据框的方法:left.merge(right, how=“inner”, on=None, left_on=None, right_on=None, suffixes=("_x", “_y”))。参数都是一样的,只是左侧的数据框成为了一个方法的对象。
另一种合并列的方法:df.join(other, on= None, how=“left”, lsuffix="",rsuffix="")
若没有指定 on
参数,则默认以索引作定位。这时必须指定左右两边相同列的后缀 lsuffix
和 rsuffix
。
>>> print(df1.join(df2, how="outer", lsuffix="_left", rsuffix="_right"))
a_left b a_right c
A 1.624345 1.0 2.0 1.0
B -0.611756 3.0 NaN NaN
C -0.528172 5.0 2.0 2.0
D -1.072969 7.0 2.0 4.0
F NaN NaN 2.0 5.0