「目录」
数据规整:聚合、合并和重塑
Data Wrangling: Join, Combine, and Reshape
- 8.1 => 层次化索引
- 8.2 => 合并数据集
--------> 数据库风格的DataFrame合并
- 8.3 => 重塑和轴向旋转
公众号的第40篇文章啦,打卡。
因为合并数据集的篇幅蛮长的,还是打算分成几篇笔记更新。
那步入正题吧。
数据库风格的DataFrame合并数据集的合并(merge)或连接(join)运算是通过一个或多个键将行链接起来的。
pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来,来看例子吧。
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: df1 = pd.DataFrame({'key':['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1':range(7)})
In [4]: df2 = pd.DataFrame({'key':['a', 'b', 'd'], 'data2':range(3)})
In [5]: df1
Out[5]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
In [6]: df2
Out[6]:
key data2
0 a 0
1 b 1
2 d 2
下面是多对一的合并。df1有多个行的键为b和a,df2中key列的每个值仅对应一行,因为key='c'只有df1有,df2没有,所以合并后也没有key='c'的行:
In [7]: pd.merge(df1, df2)
Out[7]:
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
通过传入on='key'可以指定要用哪个列进行连接,如果没有指定merge会将重复列的列名当作键:
In [8]: pd.merge(df1, df2, on='key')
Out[8]:
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
如果两个DataFrame的列名不同,也可以分别进行指定:
In [9]: df3 = pd.DataFrame({'lkey':['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1':range(7)})
In [10]: df4 = pd.DataFrame({'rkey':['a', 'b', 'd'], 'data2':range(3)})
In [11]: df3
Out[11]:
lkey data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
In [12]: df4
Out[12]:
rkey data2
0 a 0
1 b 1
2 d 2
In [13]: pd.merge(df3, df4, left_on='lkey', right_on='rkey')
Out[13]:
lkey data1 rkey data2
0 b 0 b 1
1 b 1 b 1
2 b 6 b 1
3 a 2 a 0
4 a 4 a 0
5 a 5 a 0
默认情况下,merge做的是“内连接”,结果中的键是交集,所以交集以外的'c'和'd'及与之相关的数据消失了。
其他方式还有"left"、"right"以及“outer”。外连接求取的是键的并集:
In [14]: pd.merge(df1, df2, how='outer')
Out[14]:
key data1 data2
0 b 0.0 1.0
1 b 1.0 1.0
2 b 6.0 1.0
3 a 2.0 0.0
4 a 4.0 0.0
5 a 5.0 0.0
6 c 3.0 NaN
7 d NaN 2.0
上表对不同的链接类型进行了总结,另外'output'应该是'outer'才对
多对多的合并不是很直观。看一下下面的例子吧:
先创建df1和df2,pd.merge中on='key'代表根据df1和df2中的列名'key'连接,how='left'代表使用df1所有的键。
In [15]: df1 = pd.DataFrame({'key':['b', 'b', 'a', 'c', 'a', 'b'], 'data1':range(6)})
In [16]: df2 = pd.DataFrame({'key':['a', 'b', 'a', 'b', 'd'], 'data2':range(5)})
In [17]: df1
Out[17]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
In [18]: df2
Out[18]:
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
In [19]: pd.merge(df1, df2, on='key', how='left')
Out[19]:
key data1 data2
0 b 0 1.0
1 b 0 3.0
2 b 1 1.0
3 b 1 3.0
4 a 2 0.0
5 a 2 2.0
6 c 3 NaN
7 a 4 0.0
8 a 4 2.0
9 b 5 1.0
10 b 5 3.0
原书中作者说多对多的连接产生的是行的笛卡尔积。懂啥意思不?
由于左边的DataFrame有3个"b"行,右边的DataFrame有2个"b"行,所以最终结果中就有6个"b"行。
In [24]: frame.loc['a', 'Ohio']
Out[24]:
color Green Red
key2
1 0 1
2 3 4
In [25]: frame.loc['a', ['Ohio', 'Colorado']]
Out[25]:
state Ohio Colorado
color Green Red Green
key2
1 0 1 2
2 3 4 5
如果我们要根据多个键进行合并,可以传入一个由列名组成的列表:
In [21]: left = pd.DataFrame({'key1':['foo', 'foo', 'bar'], 'key2':['one', 'two', 'one'], 'lval':[1, 2, 3]})
In [22]: right = pd.DataFrame({'key1':['foo', 'foo', 'bar', 'bar'], 'key2':['one', 'one', 'one', 'two'], 'rval':[4, 5,
...: 6, 7]})
In [23]: left
Out[23]:
key1 key2 lval
0 foo one 1
1 foo two 2
2 bar one 3
In [24]: right
Out[24]:
key1 key2 rval
0 foo one 4
1 foo one 5
2 bar one 6
3 bar two 7
In [25]: pd.merge(left, right, on=['key1', 'key2'], how='outer')
Out[25]:
key1 key2 lval rval
0 foo one 1.0 4.0
1 foo one 1.0 5.0
2 foo two 2.0 NaN
3 bar one 3.0 6.0
4 bar two NaN 7.0
在合并运算中我们有时还会遇到重复列名的问题。我们可以通过merge中suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名的字符串:
In [26]: left
Out[26]:
key1 key2 lval
0 foo one 1
1 foo two 2
2 bar one 3
In [27]: right
Out[27]:
key1 key2 rval
0 foo one 4
1 foo one 5
2 bar one 6
3 bar two 7
In [28]: pd.merge(left, right, on='key1')
Out[28]:
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
In [29]: pd.merge(left, right, on='key1', suffixes=('_left', '_right'))
Out[29]:
key1 key2_left lval key2_right 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函数的参数
先更到这里吧,下篇是索引上的合并。
BYE-BYE-BYE-BYE-BYE-BYE,下篇见
-END-
,