人生苦短, 我用 Python
前文传送门:
小白学 Python 数据分析(1): 数据分析基础 https://www.geekdigging.com/2020/01/19/6719980708/
小白学 Python 数据分析 (2):Pandas (一) 概述 https://www.geekdigging.com/2020/01/20/6718497214/
小白学 Python 数据分析 (3):Pandas (二) 数据结构 Series https://www.geekdigging.com/2020/02/04/3234667780/
小白学 Python 数据分析 (4):Pandas (三) 数据结构 DataFrame https://www.geekdigging.com/2020/02/05/9920298470/
小白学 Python 数据分析 (5):Pandas (四) 基础操作 (1) 查看数据 https://www.geekdigging.com/2020/02/16/6852411690/
小白学 Python 数据分析 (6):Pandas (五) 基础操作 (2) 数据选择 https://www.geekdigging.com/2020/02/20/6566891797/
小白学 Python 数据分析 (7):Pandas (六) 数据导入 https://www.geekdigging.com/2020/02/23/7355903936/
小白学 Python 数据分析 (8):Pandas (七) 数据预处理 https://www.geekdigging.com/2020/02/25/9013297409/
小白学 Python 数据分析 (9):Pandas (八) 数据预处理(2) https://www.geekdigging.com/2020/02/27/2857868620/
小白学 Python 数据分析 (10):Pandas (九) 数据运算 https://www.geekdigging.com/2020/02/29/5808964196/
小白学 Python 数据分析 (11):Pandas (十) 数据分组 https://www.geekdigging.com/2020/03/03/5975552137/
小白学 Python 数据分析 (12):Pandas (十一) 数据透视表(pivot_table) https://www.geekdigging.com/2020/03/04/8327177610/
说到数据表拼接, 就不得不提一下 SQL , 对于熟悉 SQL 的同学来讲, 这并不是一个难以理解的概念, 数据表之间的关系可以分为以下这三种:
一对一
两个表之间的公共列是一对一的.
这里的示例我们就不用图片了, 直接使用代码来做展示, 原因嘛就是小编懒的画了:
- import pandas as pd
- df1 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet1')
- print(df1)
- # 输出内容
编号 姓名 分数
0 100 小明 96
1 200 小红 48
2 300 小王 72
3 400 小刚 72
- df2 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet2')
- print(df2)
- # 输出内容
编号 班级
- 100 1
- 200 2
- 300 3
- 400 4
这里可以很直观的看到, 这两个表的编号是公共列, 并且唯一对应.
如果我们要讲这两个表进行连接操作, 需要使用 merge() 方法:
- print(pd.merge(df1, df2))
- # 输出内容
编号 姓名 分数 班级
0 100 小明 96 1
1 200 小红 48 2
2 300 小王 72 3
3 400 小刚 72 4
在我们使用 merge() 方法的时候, merge() 方法会自动寻找两个表中的公共列, 并且自动的进行对应操作.
一对多
两个表之间的公共列不是一对一的, 而是其中一个表的公共列是唯一的, 另一个表的公共列则会有重复的数据.
- import pandas as pd
- df1 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet1')
- print(df1)
- # 输出内容
编号 姓名 分数
0 100 小明 96
1 200 小红 48
2 300 小王 72
3 400 小刚 72
- df3 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet3')
- print(df3)
- # 输出内容
编号 分数
- 100 101
- 100 102
- 100 103
- 100 104
- 200 201
- 200 202
- 300 301
- 400 401
从上面这两个 df 中可以看到, df1 中的编号在 df3 中会对应多条数据, 我们在对这两个 df 进行连接操作的时候, 需要使用属性 on 指明判断的条件:
- print(pd.merge(df1, df3, on='编号'))
- # 输出内容
编号 姓名 分数_x 分数_y
0 100 小明 96 101
1 100 小明 96 102
2 100 小明 96 103
3 100 小明 96 104
4 200 小红 48 201
5 200 小红 48 202
6 300 小王 72 301
7 400 小刚 72 401
多对多
两个表之间的公共列都是会有重复数据的, 相当于是多个一对多.
注意理解多个一对多, 这里的逻辑稍微有点绕, 小编在第一次接触 SQL 的时候实际上是无法理解的.
我们这里新建一个 df4 , 新增一个编号为 100 的小黑, 还是通过编号对 df4 和 df3 进行连接操作:
- df4 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet4')
- print(df4)
- # 输出结果
编号 姓名 分数
0 100 小明 96
1 100 小黑 100
2 200 小红 48
3 300 小王 72
4 400 小刚 72
print(pd.merge(df4, df3, on='编号'))
编号 姓名 分数_x 分数_y
0 100 小明 96 101
1 100 小明 96 102
2 100 小明 96 103
3 100 小明 96 104
4 100 小黑 100 101
5 100 小黑 100 102
6 100 小黑 100 103
7 100 小黑 100 104
8 200 小红 48 201
9 200 小红 48 202
10 300 小王 72 301
11 400 小刚 72 401
连接方式
学过 SQL 的同学都知道, SQL 中连接分为内连接, 左连接, 右连接和外连接, 同样在 Pandas 也是一样的.
内连接
内连接就是取两个表中公共的部分, 我们重新创建一个 df5 , 在 df5 中只有编号 100 和 200 能和前面的数据保持一致:
- df5 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet5')
- print(df5)
- # 输出结果
编号 姓名 分数
0 100 小明 96
1 100 小黑 100
2 200 小红 48
3 600 想不出来叫啥了 1 600
4 700 想不出来叫啥了 2 700
- # 内连接
- print(pd.merge(df5, df3, on='编号', how='inner'))
- # 输出结果
编号 姓名 分数_x 分数_y
0 100 小明 96 101
1 100 小明 96 102
2 100 小明 96 103
3 100 小明 96 104
4 100 小黑 100 101
5 100 小黑 100 102
6 100 小黑 100 103
7 100 小黑 100 104
8 200 小红 48 201
9 200 小红 48 202
这里 how 属性是用来指定连接类型的.
左连接
左连接就是已左表为基础, 右表像左表上拼数据:
- # 左连接
- print(pd.merge(df5, df3, on='编号', how='left'))
- # 输出结果
编号 姓名 分数_x 分数_y
0 100 小明 96 101.0
1 100 小明 96 102.0
2 100 小明 96 103.0
3 100 小明 96 104.0
4 100 小黑 100 101.0
5 100 小黑 100 102.0
6 100 小黑 100 103.0
7 100 小黑 100 104.0
8 200 小红 48 201.0
9 200 小红 48 202.0
10 600 想不出来叫啥了 1 600 NaN
11 700 想不出来叫啥了 2 700 NaN
可以看到, 在 df5 中, 编号 600 和 700 的两条数据在 df3 中没有, 所以 分数_y 的值为 NaN .
右连接
右连接正好和上面的左连接相反, 已右表为基础, 左表往右表上拼数据:
- # 右连接
- print(pd.merge(df5, df3, on='编号', how='right'))
- # 输出结果
编号 姓名 分数_x 分数_y
0 100 小明 96.0 101
1 100 小黑 100.0 101
2 100 小明 96.0 102
3 100 小黑 100.0 102
4 100 小明 96.0 103
5 100 小黑 100.0 103
6 100 小明 96.0 104
7 100 小黑 100.0 104
8 200 小红 48.0 201
9 200 小红 48.0 202
- 300 NaN NaN 301
- 400 NaN NaN 401
外连接
外连接就是两个表的并集:
- # 外连接
- print(pd.merge(df5, df3, on='编号', how='outer'))
- # 输出结果
编号 姓名 分数_x 分数_y
0 100 小明 96.0 101.0
1 100 小明 96.0 102.0
2 100 小明 96.0 103.0
3 100 小明 96.0 104.0
4 100 小黑 100.0 101.0
5 100 小黑 100.0 102.0
6 100 小黑 100.0 103.0
7 100 小黑 100.0 104.0
8 200 小红 48.0 201.0
9 200 小红 48.0 202.0
10 600 想不出来叫啥了 1 600.0 NaN
11 700 想不出来叫啥了 2 700.0 NaN
- 300 NaN NaN 301.0
- 400 NaN NaN 401.0
纵向拼接
顾名思义, 纵向拼接就是在纵向上对两个表进行拼接, 当然这需要两个表具有相同的结构, 前面我们介绍的拼接方式都在横向上进行拼接.
这里我们再加入一个 df6 , 使用 df5 和 df6 演示纵向拼接, 在 Pandas 中使用纵向拼接使用的方法是 concat() :
- df6 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet6')
- print(df6)
- # 输出结果
编号 姓名 分数
0 800 起个名字好难啊 100
1 900 起个名字真的难 200
- # 纵向拼接
- print(pd.concat([df5, df6]))
- # 输出结果
编号 姓名 分数
0 100 小明 96
1 100 小黑 100
2 200 小红 48
3 600 想不出来叫啥了 1 600
4 700 想不出来叫啥了 2 700
0 800 起个名字好难啊 100
1 900 起个名字真的难 200
当我们使用 concat() 以后, 发现索引还是保留了原有的索引, 看着很不舒服, 这时我们可以设置参数 ignore_index , 让其不在保留原有索引, 而是生成新的索引:
- print(pd.concat([df5, df6], ignore_index=True))
- # 输出结果
编号 姓名 分数
0 100 小明 96
1 100 小黑 100
2 200 小红 48
3 600 想不出来叫啥了 1 600
4 700 想不出来叫啥了 2 700
5 800 起个名字好难啊 100
6 900 起个名字真的难 200
本篇的分享到这里就算结束, 如果有 SQL 基础的同学看起来应该毫无压力, 没有基础的同学推荐自己动手试一下, 很多看着不是很理解的东西一动手就立马打通任督二脉.
示例代码
老规矩, 所有的示例代码都会上传至代码管理仓库 GitHub 和 Gitee 上, 方便大家取用.
示例代码 - GitHub
示例代码 - Gitee
来源: https://www.cnblogs.com/babycomeon/p/12432957.html