查看原文
其他

数据治理 | 实操性强的Pandas数据匹配教程!

快点关注→ 数据Seminar 2022-12-31

目录

一、前言

二、何为数据匹配

三、数据匹配方式

  1. 左连接
  2. 右连接
  3. 内连接
  4. 外连接
  5. 多个连接字段
  6. 连接字段名称不同

四、总结

本文共3901字,预计阅读时间10分钟,感谢阅读!

Part1前言

之前的文章中,我们介绍了如何使用 Pandas 将多份数据合并为一份数据,包括横向合并,纵向合并以及简单的数据匹配。其中简单数据合并较为简单,数据匹配则稍麻烦一些;在实际的应用中,数据匹配对于数据使用者来说是非常重要的技能。所以本期文章将会专注为大家介绍如何使用 Pandas 进行数据匹配。
本文中所有 Python 代码均在集成开发环境 Visual Studio Code (VScode) 中使用交互式开发环境 Jupyter Notebook 编写和运行;所有 SQL 代码在数据库工具 DBeaver 中编写。

Part2何为数据匹配

数据匹配是数据之间按照某种内在关系进行配准。也就是说,能够进行数据匹配的两份数据,他们之间一定有某种内在关系。这种内在关系的现实意义一般指参与数据匹配的两份数据,必然有内容相同的数据字段(可以部分相同)。而我们通过两表中的共同字段将一张表中的部分数据字段添加到另一张表中的操作就是我们常说的数据匹配(在数据库中称为表联结或表连接),而起到连接作用的字段,我们则可以称之为连接字段
举个例子:
表 A 为学生成绩表:
  
表 B 为学生信息表:
现需要在表 A中添加一列学生性别,已知学号和性别一定是一一对应的,那么就可以利用这种关系,根据两表中的共有的学号字段来把表 B中的性别一列添加到表 A当中去。这种操作在 Excel 中可以使用 VLOOKUP 系列函数来完成,但是这种函数局限性很大,也不适合用在较大的数据集上。而 Python 和数据库则非常适合做这样的事情。
在 Python 和数据库中,表连接(数据匹配)主要有四种连接方式,分别为左连接、右连接、内连接以及外连接。
① 左连接
Table A左表Table B右表左连接后数据以左表为基准,只保留左表中连接字段原有的数据
②右连接
右连接恰恰与左连接相反,左连接后数据以右表为基准,只保留右表中连接字段原有的数据。其实这个连接方式比较鸡肋,因为当左表与右表互换位置后,它的作用就会与左连接一样。
③内连接
内连接会在两表连接后,只保留左表连接字段和右表连接字段共有的数据。
④外连接
外连接会在两表连接后,保留左表连接字段和右表连接字段所有的数据。
看完上面这些,你可能依然存在疑问,没关系,我们将在下文中使用例子分别讲解上面这些数据匹配方式。

Part3数据匹配方式

我们使用以下两张表来演示以上四种数据匹配方式。

成绩表:记录学号为01-10十位同学成绩的成绩表

信息表:记录学号为06-15,十位同学基本信息的信息表

使用 Python 读取这两张表:
# 读取学生成绩表,所有字段读取为字符型
table_score = pd.read_excel('成绩表.xlsx', dtype=str)
# 读取学生信息表,所有字段读取为字符型
table_info = pd.read_excel('信息表.xlsx', dtype=str)
同时,我们将两张表导入到 MySQL 数据库,存放在名称为 Student 的数据库下,表名称分别为table_scoretable_info

1左连接

数据匹配场景 :将信息表中的学生“性别”匹配到成绩表中

(1)使用 SQL

select A.*, B.性别 from   -- 选择 A 表所有字段和 B 表“性别”字段
Student.table_score A left join Student.table_info B  -- 左连接并分别为表取别名A,B
on A.学号 = B.学号   -- 两表的连接字段,均是学号字段
 
可以看到,成绩表左连接信息表,所得结果仍是成绩表(左表)连接字段学号原来的十位同学;由于信息表中没有学号为 01-05 的学生信息,所以所得结果中,这几位同学的性别显示为空。

(2)使用 Pandas

Pandas 中主要使用 pd.merge()df.join() 进行数据匹配,由于前者的功能更加全面,所以这里我们只介绍 pd.merge() 方法。
pd.merge() 方法的主要参数如下:
  • left:左表
  • right:右表
  • how:连接方式,可选参数有left,right,inner,outer。
  • on:两张表共同的连接字段
  • left_on:左表中的连接字段
  • right_on:右表中的连接字段,此参数必须与 left_on 一同使用。
两表左连接的 Python 代码如下:
# 信息表中仅需要连接字段“学号”和所需字段“性别”,所以只取两个字段即可
df_left = pd.merge(left=table_score,
                   right=table_info[['学号','性别']],
                   how='left',
                   on='学号')
df_left 
  
这和使用 SQL 数据匹配达到的效果是一致的。

2右连接

数据匹配场景 :将成绩表中的中的“语文”成绩匹配到信息表中

(1)使用 SQL

select A.语文, B.* from 
Student.table_score A right join Student.table_info B
on A.学号 = B.学号 
  
可以看到,成绩表右连接信息表,所得结果是信息表(右表)连接字段学号原来的十位同学;由于成绩表中没有学号 11-15 的学生信息,所以所得结果中,这几位同学的“语文”成绩显示为空。

(2)使用 Pandas

# 成绩表中仅需要连接字段“学号”和所需字段“语文”,只取这两个字段
df_right = pd.merge(left=table_score[['学号','语文']],
                   right=table_info,
                   how='right',
                   on='学号')
df_right
  
与 SQL 的结果相比,仅字段顺序上存在差异。

3内连接

数据匹配场景 :将成绩表和信息表的所有字段匹配在一起,保留两张表中都有的学生的数据。

(1)使用 SQL

select * from 
Student.table_score A inner join Student.table_info B
on A.学号 = B.学号 
  
可以看到,两表内连接后,结果只保留了两张表中连接字段“学号”的共同值。另外,信息表中的“学号”和“姓名”两个重复的字段都得以保留。

(2)使用 Pandas

df_inner = pd.merge(left=table_score,
                   right=table_info,
                   how='inner',
                   on='学号')
df_inner
  
与 SQL 相比,使用 Pandas 进行内连接后,仍然只保留了两张表中连接字段“学号”的共同值。但是连接字段“学号”只保留了一个,而且两个表中的“姓名”字段虽然出现重复,但是 Pandas 自动为两个字段做了区分标记。这个标记可以使用参数 suffixes 来控制,但是不能设置空的标记。

4外连接

数据匹配场景 :将成绩表和信息表的所有字段匹配在一起,保留两张表中全部数据。

(1)使用 SQL

MySQL 不支持直接进行外连接,但是可以通过合并左连接的结果和右连接的结果来实现外连接。
select * from 
Student.table_score A left join Student.table_info B
on A.学号 = B.学号 --左连接结果
union -- 合并
select * from 
Student.table_score A right join Student.table_info B
on A.学号 = B.学号 --右连接结果
  
可以看出,由于成绩表中没有学号为11-15的学生成绩,而信息表中没有学号为01-05的学生信息,所以对应的部分为空。

(2)使用 Pandas

pd.merge() 方法支持直接进行外连接,不需要合并数据。
df_outer = pd.merge(left=table_score,
                   right=table_info,
                   how='outer',
                   on='学号')
df_outer
  
这个结果与 SQL 所得结果略有差异,由于 Pandas 连接结果不会重复显示连接字段,所以连接字段“学号”是完整的01-15

5多个连接字段

假设学校的教务系统出现问题,导致学号并不能与学生一一对应,即仅通过学号不能唯一识别一位同学;但是同时使用学号,姓名一定可以唯一识别一位同学。那么这种需要多个连接字段的数据匹配需要怎么做呢?
这里我们以左连接为例来说明。
数据匹配场景 :将信息表中的学生“性别”匹配到成绩表中

(1)使用 SQL

select A.*, B.性别 from 
Student.table_score A left join Student.table_info B
on A.学号 = B.学号 and A.姓名 = B.姓名  --使用 and 连接两个条件

(2)使用 Pandas

当有多个连接字段时,需要将所有连接字段的名称存放在一个列表或元组中。
df_left = pd.merge(left=table_score,
                   right=table_info[['学号','姓名','性别']],
                   how='left',
                   on=['学号','姓名'])
df_left

6连接字段名称不同

假设信息表中的学号字段不再是“学号”,而是“ID”,我们如何在不修改字段名称的情况下完成数据匹配呢?

(1)使用 SQL

select A.*, B.性别 from 
Student.table_score A left join Student.table_info B
on A.学号 = B.ID  -- 注意两个字段名称

(2)使用 Pandas

由于连接字段的名称不相同,所以使用 pd.merge() 时不可以再使用on参数,转而使用 left_on参数和right_on参数分别代表两张表的连接字段。
df_left = pd.merge(left=table_score,
                   right=table_info[['学号','姓名','性别']],
                   how='left',
                   left_on='学号',
                   right_on='ID')
df_left

Part4总结

本文详细介绍了使用 Pandas 进行数据匹配的方法,并与数据库做了深度对比。数据匹配是处理表格数据中的高端操作,在处理多个关联性强的数据时,这种方法可以帮我们快速地帮助我们匹配数据,实现更多元化的需求。

我们将在数据治理板块中推出一系列原创推文,帮助读者搭建一个完整的社科研究数据治理软硬件体系。该板块将涉及以下几个模块(点击标题即可跳转至相应合集):

  1. 计算机基础知识
  2. 编程基础
  3. 数据采集
  4. 数据存储
  5. 数据清洗
  6. 数据实验室搭建



星标⭐我们不迷路!想要文章及时到,文末“在看”少不了!

点击搜索你感兴趣的内容吧


往期推荐


基本无害 | 实证研究中必须要“自问自答”的四个问题

基本无害 | 前言:关于计量的基本观点与本书主要特点

基本无害 | 专栏发刊词

数据治理 | 数据分析与清洗工具:Pandas 数据合并

数据治理 | 数据分析与清洗工具:Pandas 创建新字段( 赠送本文同款数据!)

数据治理 | 数据分析与清洗工具:Pandas 数据类型转换(赠送本文同款数据!!)

数据治理 | 数据分析与清洗工具:Pandas 缺失值与重复值处理






数据Seminar




这里是大数据、分析技术与学术研究的三叉路口


文 | 《社科领域大数据治理实务手册》


    欢迎扫描👇二维码添加关注    

点击下方“阅读全文”了解更多

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存