文章目录
- 三个函数的区别
- concat()
- append()
- merge()
- 三个函数各自的拓展用法
- concat()
- 连接多个DataFrame
- 设置特定的键(key)
- 横向合并两个DataFrame
- append()
- 连接多个DataFrame
- merge()
- 指定两个列名连接DataFrame
- merge()的四种连接方式
- concat()
1. 三个函数的区别
concat(), append(), merge()一般都是用来连接两个或者多个DataFrame对象。其中, concat(), append()默认用来纵向连接DataFrame对象, merge()用来横向连接DataFrame对象。
接下来我们来看看具体的例子。
1.1 concat()
concat()默认情况下是纵向连接两个DataFrame:
# 初始化df1
![212db47bb08d54fa5b653e39d2e68d90.png](https://i-blog.csdnimg.cn/blog_migrate/6fa5f4a70c50be5806ba8ddcbc880a5b.png)
# 初始化df2
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
'B': ['B4', 'B5', 'B6', 'B7'],
'C': ['C4', 'C5', 'C6', 'C7'],
'D': ['D4', 'D5', 'D6', 'D7']})
df2
![ad5271f04fff9a1d91cfce76170e121f.png](https://i-blog.csdnimg.cn/blog_migrate/df6dae28374d678320c77da52e06489b.png)
# concat : 纵向连接df1和df2。
result = pd.concat([df1, df2])
result
![84d1c5da736fb84beaf831991b9259da.png](https://i-blog.csdnimg.cn/blog_migrate/0b98ab508e738d09961504334cc2881a.png)
我们看到df1, df2纵向合并在了一起。但也注意到, 因为concat()保留了每个子DataFrame的index, 所以合并之后的DataFrame中, 每个index出现了两次。
我们可以通过设置ignore_index=False来解决这个问题:
result = pd.concat([df1, df2], ignore_index=True)
result
![88ab4ec9c12b4f1e254660e23adf16b9.png](https://i-blog.csdnimg.cn/blog_migrate/24e2a1b39ccaf60486a316fc0a2560ce.png)
可以看到, 设置了ignore_index=True之后, 合并之后的DataFrame对index重新进行了排序。
1.2 append()
append()的默认操作效果跟concat()相同, 都是实现两个DataFrame的纵向连接。事实上可以把它看做concat()的早期版本:
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df1
![272f86586e9f9093c93ad33499c728b2.png](https://i-blog.csdnimg.cn/blog_migrate/15b7543205ce6e73b8ab1471728d83a1.png)
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
'B': ['B4', 'B5', 'B6', 'B7'],
'C': ['C4', 'C5', 'C6', 'C7'],
'D': ['D4', 'D5', 'D6', 'D7']})
df2
![cef8ec67fd3c08bcd3e3535e6da46f19.png](https://i-blog.csdnimg.cn/blog_migrate/e86ba640a26875b228e3085767bd23f1.png)
result = df1.append(df2)
result
![2f1a3717fe11d80d18f9f6de23e1f72f.png](https://i-blog.csdnimg.cn/blog_migrate/0602d612c6ebf1f59a71d5d23b1beb3e.png)
可以看到我们得到了跟concat()默认操作同样的结果。因为append()也保留了每个子DataFrame的index, 所以合并之后的DataFrame中, 每个index出现了两次。
我们同样可以通过设置ignore_index=False来解决这个问题:
result = df1.append(df2, ignore_index=True)
result
![200d5180c201cc9babfefe7ca3e3f26d.png](https://i-blog.csdnimg.cn/blog_migrate/26dc28a847d2f9c182075c97cea18032.png)
1.3 merge()
merge()的默认操作是横向连接两个DataFrame对象:
left = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']})
left
![224a82cbef9f752af71b55dd1e4779f0.png](https://i-blog.csdnimg.cn/blog_migrate/1541cfda5e817300bc86d8ee8e060094.png)
right = pd.DataFrame({'key': ['K1', 'K2', 'K3'],
'C': ['C1', 'C2', 'C3'],
'D': ['D1', 'D2', 'D3']})
right
![180ea72d6c7f1a38f89f7b7ee21a2143.png](https://i-blog.csdnimg.cn/blog_migrate/8968cda365f2a5b2b7a687500bdf7aba.png)
# 横向合并left和right两个子DataFrame。
## on='key' : 把两个子DataFrame中key列相同的值连接到一行上。
result = pd.merge(left, right, on='key')
result
![3b1ea98e0513d3c5672ccc29e397bfd0.png](https://i-blog.csdnimg.cn/blog_migrate/071c010b12b81fc3f93a028320424993.png)
从上面的结果可以看出, merge()方法把两个子DataFrame中key列相同的值连接到了一行上, 并且删去了key列值不相同的行。
如果想保留key列值不相同的行, 可以添加上how='outer'参数:
# how: 指定两个子DataFrame的连接方式,
result = pd.merge(left, right, on='key', how='outer')
result
![c776dea3cd62656694f084791d50e1a7.png](https://i-blog.csdnimg.cn/blog_migrate/e2d0e98a284445f810a3a1ec38d08409.png)
2. 三个函数各自的拓展用法
2.1 concat()
- 2.1.1 连接多个DataFrame
concat()可以一次性连接3个或者3个以上的DataFrame:
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df1
![7ee5db074fca6c009b528347d232b43d.png](https://i-blog.csdnimg.cn/blog_migrate/a94b6a562adf7854120e5c6dbb50490d.png)
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
'B': ['B4', 'B5', 'B6', 'B7'],
'C': ['C4', 'C5', 'C6', 'C7'],
'D': ['D4', 'D5', 'D6', 'D7']})
df2
![132bf82211112445a41943a3f5f4f522.png](https://i-blog.csdnimg.cn/blog_migrate/e30e1490ef618722bc144fb0a8cf8e72.png)
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
'B': ['B8', 'B9', 'B10', 'B11'],
'C': ['C8', 'C9', 'C10', 'C11'],
'D': ['D8', 'D9', 'D10', 'D11']})
df3
![6644392cb1198f70a4ba6f1efe80bc1d.png](https://i-blog.csdnimg.cn/blog_migrate/d9f7f0080d355318fb73709d2c6ff34a.png)
result = pd.concat([df1, df2, df3])
result
![bc9c32120ff6fcbd4dc205f45086c1c8.png](https://i-blog.csdnimg.cn/blog_migrate/efde5f76562161e76361f7648affaeeb.jpeg)
- 2.1.2 设置特定的键(key)
有时候我们需要区分合并之后的DataFrame里, 哪些数据是来自df1的,哪些数据是来自df2的。这个时候我们可以给它们设置一个特定的键(key), 相当于给它们起个名字, 这样我们就可以把它们区分开来了。
# 为每个子DataFrame设置一个特定的键(key)
result = pd.concat([df1, df2], keys=['df1', 'df2'])
result
![7c284f679b9723a88a712a5bb0122c79.png](https://i-blog.csdnimg.cn/blog_migrate/04dd285dca4ce5c01351974ef68b1c6b.png)
可以看到, 在合并后的DataFrame里, 我们用key把每个子DataFrame的数据标识了出来。
我们可以通过下面的方式取用某个子DataFrame的数据:
result.loc['df1']
![342241f03bd90845f1cf796947cb83eb.png](https://i-blog.csdnimg.cn/blog_migrate/7ac4392d44ed5f0f6b7c6e28ef20b6fa.png)
- 2.1.3 横向合并两个DataFrame
默认情况下, concat()纵向合并两个子DataFrame, 但通过设置axis=1参数之后, 我们也可以横向合并两个DataFrame。
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df1
![0d9639f9091eb10767f5bf131ef9df60.png](https://i-blog.csdnimg.cn/blog_migrate/47cedeb441cfb870b78daa54c29c0d76.png)
# 准备一组新的数据df4
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
'D': ['D2', 'D3', 'D6', 'D7'],
'F': ['F2', 'F3', 'F6', 'F7']},
index=[2, 3, 6, 7])
df4
![1540e7005ce5e02a7ce1e7646550accd.png](https://i-blog.csdnimg.cn/blog_migrate/d51b2150e394c1f8005cabbd27975b9e.png)
result = pd.concat([df1, df4], axis=1)
result
![a449f608aaf018524ecfd58180868fde.png](https://i-blog.csdnimg.cn/blog_migrate/33b17da8f5e2eb11845909a2381ce0b7.png)
从上面的结果可以看到, 设置了axis=1之后, df1和df4两个DataFrame横向地结合在了一起。两个DataFrame有着相同index的行连成了一行, index不相同的行各自占一行的内容。
如果只想保留有着相同index的行, 可以添加上join=‘inner’参数:
result = pd.concat([df1, df4], axis=1, join='inner')
result
![89442e83115f4b241fb3a943841512ee.png](https://i-blog.csdnimg.cn/blog_migrate/87b8489551afa1d3bbc051c70d48db92.png)
如果想保留某个子DataFrame的index所在的行, 比如df1中index为0-3的行, 可以加上join_axes=[df1.index]参数:
result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])
result
![7e967854ac77ece0ac5bd8fc6a88de0a.png](https://i-blog.csdnimg.cn/blog_migrate/21ede96bb741a3a892ddc3877f9bf654.png)
2.2 append()
- 2.2.1 连接多个DataFrame
和concat()一样, append()也可以一次性连接3个或者3个以上的DataFrame:
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df1
![31e407e7fa5cb224150cdedd00b26b92.png](https://i-blog.csdnimg.cn/blog_migrate/c551833f609258ecf14ab402a09b3644.png)
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
'B': ['B4', 'B5', 'B6', 'B7'],
'C': ['C4', 'C5', 'C6', 'C7'],
'D': ['D4', 'D5', 'D6', 'D7']})
df2merge()
![f8bfa754feb2782e076e7af3417bcf41.png](https://i-blog.csdnimg.cn/blog_migrate/52052089f718101e073c55060b9ee3d8.png)
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
'B': ['B8', 'B9', 'B10', 'B11'],
'C': ['C8', 'C9', 'C10', 'C11'],
'D': ['D8', 'D9', 'D10', 'D11']})
df3
![c600afceb95a90925793ebb64a44352d.png](https://i-blog.csdnimg.cn/blog_migrate/979f8e8929df72a1433316cca5f23de5.png)
result = df1.append([df2, df3])
result
![65ab417cfa4d5f83ad3f7f35e5fa2cb0.png](https://i-blog.csdnimg.cn/blog_migrate/c881ef3a9f5113deb64db8ad36d12943.jpeg)
2.3 merge()
- 2.3.1 指定两个列名连接DataFrame
我们可以在on参数里指定两个或者两个以上的列名对DataFrame进行连接:
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
left
![2bc8080d963d2c4d2f931acfe33d34e2.png](https://i-blog.csdnimg.cn/blog_migrate/3a44fc801821761a9d155260c62075f5.png)
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
right
![558cdf70f994361f987613799d2a8452.png](https://i-blog.csdnimg.cn/blog_migrate/4dbafb489b8dd5bb851089574b56920e.png)
result = pd.merge(left, right, on=['key1', 'key2'])
result
![31fcb9025c551cefb3dfd0860d900c96.png](https://i-blog.csdnimg.cn/blog_migrate/0c7736f076f826f9fd205e2b2b4ee821.png)
在上面的例子里, 我们在on参数里设置了key1, key2两个值, 于是在连接left和right两个DataFrame的时候, 会把key1, key2都相等的行连在一起, 而key1, key2不完全相等的行则会被舍弃掉。
- 2.3.2 merge()的四种连接方式
merge()的how参数可以设置DataFrame的四种连接方式:左连接(left), 右连接(right), 外连接(outer), 内连接(inner)。
内连接(inner)是merge()的默认连接方式, 当how中不设置任何参数的时候, merge()用的是内连接(inner)方式。 也就是我们在上面的例子中所看到的, key值不完全相同的行便不会显示在最终的结果里 :
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
left
![d9bbe9a5fe38e35d4704f2d3436666a8.png](https://i-blog.csdnimg.cn/blog_migrate/32f0c2ddfd54128e7677596e8d7a67c1.png)
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
right
![ca0748e72699a0749952ad82f04c2098.png](https://i-blog.csdnimg.cn/blog_migrate/b19a3a8c3cd8edebb2c4cce6e2844b13.png)
result = pd.merge(left, right, on=['key1', 'key2'],
how='inner')
result
![9ad8f3c8010fdb7be606b3891df98c00.png](https://i-blog.csdnimg.cn/blog_migrate/0cba2c8a8c3a270b4f0a9d9bc24bfae8.png)
外连接(outer)则会保留两个DataFrame中所有的行:
result = pd.merge(left, right, on=['key1', 'key2'],
how='outer')
result
![125f27087e578b025fb026ad75b9238b.png](https://i-blog.csdnimg.cn/blog_migrate/41700979dbd4e35109171be391ea9d87.png)
左连接(left)则会保留左边的子DataFrame中所有的行:
result = pd.merge(left, right, on=['key1', 'key2'],
how='left')
result
![5f83e092779628e6ba401fecb8132c98.png](https://i-blog.csdnimg.cn/blog_migrate/94dedb9b923845eb889336ae2c11d179.png)
右连接(right)则会保留右边的子DataFrame中所有的行:
result = pd.merge(left, right, on=['key1', 'key2'],
how='right')
result
![8b8fb7dd5f8bd2a6329dd4487276f7d3.png](https://i-blog.csdnimg.cn/blog_migrate/857044241218bbe72bbc1ad01fdc8f8c.png)
以上便是本篇文章的内容。
参考资料:
https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html