小白学 Python 数据分析(13):Pandas (十二)数据表拼接

人生苦短,我用 Python

前文传送门:

小白学 Python 数据分析(1):数据分析基础

小白学 Python 数据分析(2):Pandas (一)概述

小白学 Python 数据分析(3):Pandas (二)数据结构 Series

小白学 Python 数据分析(4):Pandas (三)数据结构 DataFrame

小白学 Python 数据分析(5):Pandas (四)基础操作(1)查看数据

小白学 Python 数据分析(6):Pandas (五)基础操作(2)数据选择

小白学 Python 数据分析(7):Pandas (六)数据导入

小白学 Python 数据分析(8):Pandas (七)数据预处理

小白学 Python 数据分析(9):Pandas (八)数据预处理(2)

小白学 Python 数据分析(10):Pandas (九)数据运算

小白学 Python 数据分析(11):Pandas (十)数据分组

小白学 Python 数据分析(12):Pandas (十一)数据透视表(pivot_table)

引言

说到数据表拼接,就不得不提一下 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)

# 输出内容
    编号  班级
0  100   1
1  200   2
2  300   3
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)

# 输出内容
    编号   分数
0  100  101
1  100  102
2  100  103
3  100  104
4  200  201
5  200  202
6  300  301
7  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
10  300  NaN    NaN   301
11  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
12  300       NaN    NaN  301.0
13  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

posted @ 2020-03-07 10:40  极客挖掘机  阅读(671)  评论(0编辑  收藏  举报