23

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

 4 years ago
source link: http://www.cnblogs.com/babycomeon/p/12432957.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

VJvuIzE.jpg!web

人生苦短,我用 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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK