Pandas 的Merge函数详解

在日常工作中,我们可能会从多个数据集中获取数据,并且希望合并两个或多个不同的数据集。这时就可以使用Pandas包中的Merge函数。在本文中,我们将介绍用于合并数据的三个函数

merge

merge_ordered

merge_asof

merge

merge函数是Pandas中执行基本数据集合并的首选函数。函数将根据给定的数据集索引或列组合两个数据集。

我们使用下面试示例:

 import pandas as pdcustomer = pd.DataFrame({'cust_id': [1,2,3,4,5],'cust_name': ['Maria', 'Fran', 'Dominique', 'Elsa', 'Charles'],'country': ['German', 'Spain', 'Japan', 'Poland', 'Argentina']})order = pd.DataFrame({'order_id': [200, 201,202,203,204],'cust_id':[1,3,3,4,2],'order_date': ['2014-07-05', '2014-07-06', '2014-07-07', '2014-07-07', '2014-07-08'],'order_value': [10.1, 20.5, 18.7, 19.1, 13.5]})

我们尝试模拟两个不同的数据集:客户和订单数据,其中cust_id列同时存在于两个DataFrame中。

 pd.merge(customer, order)

默认情况下,merge函数是这样工作的:

将按列合并,并尝试从两个数据集中找到公共列,使用来自两个DataFrame(内连接)的列值之间的交集。

列和索引合并

在上面合并的数据集中,merge函数在cust_id列上连接两个数据集,因为它是唯一的公共列。我们也可以指定要在两个数据集上连接的列名。

如果两个列的名称都存在于两个DataFrame中,则可以使用参数on。

 pd.merge(customer, order, on = 'cust_id')

结果与前面的示例类似,因为cust_id是唯一的公共列。但是如果两个DataFrame都包含两个或多个具有相同名称的列,则这个参数就很重要。

我们来创建一个包含两个相似列的数据。

 customer = pd.DataFrame({'cust_id': [1,2,3,4,5],'cust_name': ['Maria', 'Fran', 'Dominique', 'Elsa', 'Charles'],'country': ['German', 'Spain', 'Japan', 'Poland', 'Argentina']})order = pd.DataFrame({'order_id': [200, 201,202,203,204],'cust_id':[1,3,3,4,2],'order_date': ['2014-07-05', '2014-07-06', '2014-07-07', '2014-07-07', '2014-07-08'],'order_value': [10.1, 20.5, 18.7, 19.1, 13.5],'country' : ['German', 'Indonesia', 'Armenia', 'Singapore', 'Japan']})

数据集现在包含两个名称相似的列:cust_id和country。让我们看看如果使用默认方法合并两个DataFrame会发生什么。

 pd.merge(customer, order)

只剩下一行了,这是因为merge函数将使用与键名相同的所有列来合并两个数据集。所以现在是通过cust_id和country中找到的相同值来实现合并的。

还有一个问题,我们指定一个列后,其他的重复列(这里是country),现在存在country_x和country_y列。这两列是来自各自数据集的国家列。country_x来自Customer数据集,country_y来自Order数据集。

为了帮助区分合并过程中相同列名的结果,我们可以将一个元组对象传递给suffix参数。

 pd.merge(customer, order, on ='cust_id', suffixes = ('_customer', '_order'))

使用suffix参数,可以让我们避免混淆,或者在合并前我们直接将列改名

 customer = customer.rename(columns = {'country':'customer_country'})order = order.rename(columns = {'country':'delivery_country'})

这样就不会造成混淆了。

然是如果我们要合并的列名在两个数据集不同时,on参数就没有效果了,这时就需要使用left_on和right_on参数,我们这里以刚刚改名的country列为例:

 pd.merge(customer, order, left_on = 'customer_country', right_on = 'delivery_country',suffixes = ('_customer', '_order'))

在上面的代码中,我们将左侧数据集(Customer)上想要合并的列传递给left_on参数,将右侧数据集(Order)的列名传递给right_on参数。

left_on和right_on参数是串联工作的,因此我们不能在left_on参数中传递列名,而将right_on参数保留为空。

我们也可以使用left_index和right_index来替换left_on和right_on参数。right_index和left_index参数控制merge函数,以根据索引而不是列连接数据集。

 pd.merge(customer, order, left_index = True,  right_on = 'cust_id', suffixes = ('_customer', '_order'))

在上面的代码将True值传递给left_index参数,表示希望使用左侧数据集上的索引作为连接键。合并过程类似于下图。

当我们按索引和列合并时,DataFrame结果将由于合并(匹配的索引)会增加一个额外的列。

合并类型介绍

默认情况下,当我们合并数据集时,merge函数将执行Inner Join。在Inner Join中,根据键之间的交集选择行。匹配在两个键列或索引中找到的相同值。

下图显示了Inner Join图,其中只选择了Customer和Order数据集上的列和/或索引之间匹配的值。

 pd.merge(customer, order, left_on = 'customer_country',  right_on = 'delivery_country', suffixes = ('_customer', '_order'),how = 'inner')

我们也可以使用左连接和右连接来保留想要的DataFrame。

 pd.merge(customer, order, left_on = 'customer_country',  right_on = 'delivery_country', suffixes = ('_customer', '_order'),how = 'left', indicator = True)

上面的代码,所有与订单数据值不匹配的客户数据值都用NaN值填充。

indicator=True参数,将创建_merge列。在上面的结果中,可以看到两个值都表明该行来自DataFrame和left_only的交集,其中该行来自第一个DataFrame(左侧)。

如果要执行右连接,可以使用以下代码。

 pd.merge(customer, order, left_on = 'customer_country',  right_on = 'delivery_country', suffixes = ('_customer', '_order'),how = 'right', indicator = True)

还可以在合并过程中使用外连接来保留两个DataFrame。我们可以把外连接看作是同时进行的左连接和右连接。

最后就是交叉连接,将合并两个DataFrame之间的每个数据行。

让我们用下面的代码尝试交叉连接。

 pd.merge(customer, order, how = 'cross', suffixes = ('_customer', '_order'))

DataFrame将Customer数据中的每一行都与Order数据结合起来。

merge_ordered

在 Pandas 中,

merge_ordered

是一种用于合并有序数据的函数。它类似于

merge

函数,但适用于处理时间序列数据或其他有序数据。

merge_ordered

在合并时会保留原始数据的顺序,并且支持对缺失值进行处理。

 pd.merge_ordered(customer, order)

默认情况下,merge_ordered将执行Outer Join并根据连接键对数据进行排序。我们也可以像更改合并类型一样调整how参数。

merge_ordered是为有序数据(如时间序列)开发的。所以我们创建另一个名为Delivery的数据集来模拟时间序列数据合并。

 order = pd.DataFrame({'order_id': [200, 201,202,203,204],'cust_id':[1,3,3,4,2],'order_date': ['2014-07-05', '2014-07-06', '2014-07-07', '2014-07-07', '2014-07-08'],'order_value': [10.1, 20.5, 18.7, 19.1, 13.5],'delivery_country' : ['German', 'Indonesia', 'Armenia', 'Singapore', 'Japan']})delivery = pd.DataFrame({'delivery_date': ['2014-07-06', '2014-07-08', '2014-07-09', '2014-07-10'], 'product': ['Apple', 'Apple', 'Orange', 'Orange']})

让我们假设delivery_date是投递时间,它包含与Order数据集中的order_date一起使用。另外就是我们还需要将日期列转换为datetime对象。

 order['order_date'] = pd.to_datetime(order['order_date'])delivery['delivery_date'] = pd.to_datetime(delivery['delivery_date'])

让我们尝试按日期列合并两个数据集。

 pd.merge_ordered(order, delivery, left_on = 'order_date', right_on = 'delivery_date')

合并的DataFrame是按连接键排序的Order和Delivery数据集的Outer Join结果。

由于是外连接,一些数据点是空的。对于merge_ordered,有一个选项可以通过使用fill_method参数来填充缺失的值。

 pd.merge_ordered(order, delivery, left_on = 'order_date', right_on = 'delivery_date', fill_method = 'ffill' )

在上面的DataFrame中执行前向填充方法来计算缺失的值。

最后merge_ordered函数还可以基于数据集列执行DataFrame分组,并将它们一块一块地合并到另一个数据集。

 pd.merge_ordered(order, delivery, left_on = 'order_date', right_on = 'delivery_date', right_by = 'product')

在上面的代码中将product列传递给right_by参数,这样product列中的每个值都映射到每个可用行,并且用于对数据进行分组的同一DataFrame中不存在的数据用NaN填充。

为了进一步理解,我们在合并之前添加日期来对数据进行分组。

 pd.merge_ordered(order, delivery, left_on = 'order_date', right_on = 'delivery_date', right_by = ['delivery_date','product'])

在上面的合并过程中,我们最终得到了4个不同的组:

     ['2014–07–06', 'Apple'],['2014–07–08', 'Apple'],['2014–07–09', 'Orange'],['2014–07–10', 'Orange']

该组基于所使用列中的现有行,因此它不是所有惟一值的组合。例如,没有[’ 2014-07-09 ',‘Apple’]组,因为此数据不存在。

在上面的DataFrame中可以看到Order数据集中的每一行都映射到Delivery数据集中的组。

merge_asof

merge_asof

是一种用于按照最近的关键列值合并两个数据集的函数。这个函数用于处理时间序列数据或其他有序数据,并且可以根据指定的列或索引按照最接近的值进行合并。

 order = pd.DataFrame({'order_id': [199, 200, 201,202,203,204],'cust_id':[1,1,3,3,4,2],'order_date': ['2014-07-01', '2014-07-05', '2014-07-06', '2014-07-07', '2014-07-07', '2014-07-08'],'order_value': [11, 10.1, 20.5, 18.7, 19.1, 13.5],'delivery_country' : ['Poland', 'German', 'Indonesia', 'Armenia', 'Singapore', 'Japan']})delivery = pd.DataFrame({'delivery_date': ['2014-07-06', '2014-07-08', '2014-07-09', '2014-07-10'], 'product': ['Apple', 'Apple', 'Orange', 'Orange']})

使用merge_asof函数的一个注意事项是,必须按键对两个DataFrame进行排序。这是因为它将根据键的距离合并键,而未排序的DataFrame将抛出错误消息。

使用merge_asof类似于其他的合并操作,需要传递想要合并的DataFrame及其键名称。

 pd.merge_asof(order, delivery, left_on = 'order_date', right_on = 'delivery_date')

我们可以看到一些数据被合并了,但不是精确的值匹配。比如在第三行和第四行,order_date值为“2014-07-07”,但delivery_date为“2014-07-06”。

使用merge_asof会丢失数据。默认情况下它查找最接近匹配的已排序的键。在上面的代码中,与delivery_date不完全匹配的order_date试图在delivery_date列中找到与order_date值较小或相等的键。

delivery_date中小于等于order_date’ 2014-07-07 ‘的值为’ 2014-07-06 '。这就是为什么合并发生在这个键上。而order_date ’ 2017-04-01 ‘和’ 2017-04-05 '根本没有匹配,因为在delivery_date中没有小于或等于它们的值的值。

如果在正确的DataFrame中有多个重复的键,则只有最后一行用于合并过程。例如将更改delivery_date数据,使其具有多个不同产品的“2014-07-06”值。

 delivery = pd.DataFrame({'delivery_date': ['2014-07-06', '2014-07-06', '2014-07-08', '2014-07-10'], 'product': ['Apple', 'Orange', 'Apple', 'Orange']})

然后我们将执行与之前相同的合并过程。

 pd.merge_asof(order, delivery, left_on = 'order_date', right_on = 'delivery_date')

可以看到,合并过程对Orange产品而不是Apple产品使用delivery_date ,尽管两者具有相同的键值。另外具有精确匹配的键也会受到影响,它们会选择最后一行键。

可以通过设置allow_exact_matches=False来关闭精确匹配合并。

 pd.merge_asof(order, delivery, left_on = 'order_date', right_on = 'delivery_date', allow_exact_matches = False)

通过使用direction 参数来改变查找键的策略。例如使用向前策略:

 pd.merge_asof(order, delivery, left_on = 'order_date', right_on = 'delivery_date', direction = 'forward')

向前策略与向后策略类似,不同之处在于该函数将通过查看大于或等于正确DataFrame键的值来尝试合并。

另一个可以使用的策略是就近策略。在这个策略中使用向后或向前策略;取绝对距离中最近的那个。如果有多个最接近的键或精确匹配,则使用向后策略。

 pd.merge_asof(order, delivery, left_on = 'order_date',right_on = 'delivery_date', direction = 'nearest')

最后还可以通过使用tolerance 参数来控制键之间的距离。

 pd.merge_asof(order, delivery, left_on = 'order_date', right_on = 'delivery_date', direction = 'forward', tolerance = pd.Timedelta(1, 'd'))

在上面的示例中,只有第一行包含缺失值。这是因为order_date第一行与最近的日期delivery_date之间的距离大于一天。第二行成功合并,因为只差一天。

总结

Pandas函数提供了Merge函数可以轻松的帮助我们合并数据,而merge_ordered函数和merge_asof可以帮助我们进行更加定制化的合并工作,虽然这两个函数可能并不常见,但是它们的确在一些特殊的需求上非常的好用。

https://avoid.overfit.cn/post/9928a4b397734cfcb4aea5a232eec095

作者:Cornellius Yudha Wijaya

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何实现对主机的立体监控?

主机监控是保证系统稳定性和性能的重要环节之一,那应该如何实现对主机的立体监控? 本期EasyOps产品使用最佳实践,我们将为您揭晓: 主机应该如何分组和管理? 主机监控应该关注哪些关键性指标? 背 景 通…

MySQL建表和增添改查

1.创建一个名为mydb的数据库 mysql> show database mydb; 查询 mysql> show database mydb; 2.创建一个学生信息表 mysql> create table mydb.student_informtion( -> student_id int UNSIGNED NOT NULL PRIMARY KEY, //非空(不允许为空&#xff0…

FastAPI(七)应用配置

目录 一、在apps下新建文件夹config 二、新建配置文件app_conf.py 一、在apps下新建文件夹config 二、新建配置文件app_conf.py from functools import lru_cachefrom pydantic.v1 import BaseSettingsclass AppConfig(BaseSettings):app_name: str "Windows10 插件&qu…

WGS_1984_UTM、WGS_1984_Mercator坐标转化为经纬度坐标python

1、遥感影像的PROJECTION有哪些 遥感影像常见的投影类型有很多,具体选择哪种投影方式取决于数据的特性和使用需求。以下列举了一些常见的遥感影像投影类型: UTM (Universal Transverse Mercator) 投影:最常见的投影类型之一,将地…

uboot详解

uboot入口 在PC机上引导程序一般由BIOS开始执行,然后读取硬盘中位于MBR(Main Boot Record,主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动…

Unity之ShaderGraph 节点介绍 UV节点

UV节点 Flipbook(翻页或纹理帧动画) Polar Coordinates(将输入 UV 的值转换为极坐标。) Radial Shear(径向剪切变形) Rotate(将UV 的值旋转) Spherize(鱼眼镜头的球形变…

Spring系列三:基于注解配置bean

文章目录 💗通过注解配置bean🍝基本介绍🍝快速入门🍝注意事项和细节 💗自己实现Spring注解配置Bean机制🍝需求说明🍝思路分析🍝注意事项和细节 💗自动装配 Autowired&…

【基于IDEA + Spark 3.4.1 + sbt 1.9.3 + Spark MLlib 构建逻辑回归鸢尾花分类预测模型】

逻辑回归进行鸢尾花分类的案例 背景说明: 基于IDEA Spark 3.4.1 sbt 1.9.3 Spark MLlib 构建逻辑回归鸢尾花分类预测模型,这是一个分类模型案例,通过该案例,可以快速了解Spark MLlib分类预测模型的使用方法。 依赖 ThisBui…

maven 删除下载失败的包

本文介绍了当Maven包报红时,使用删除相关文件的方法来解决该问题。文章详细说明了_remote.repositories、.lastUpdated和_maven.repositories文件的作用,以及如何使用命令行删除这些文件。这些方法可以帮助开发者解决Maven包报红的问题,确保项…

Linux 中利用设备树学习Ⅳ

系列文章目录 第一章 Linux 中内核与驱动程序 第二章 Linux 设备驱动编写 (misc) 第三章 Linux 设备驱动编写及设备节点自动生成 (cdev) 第四章 Linux 平台总线platform与设备树 第五章 Linux 设备树中pinctrl与gpio(…

OBD针脚定义参考

OBD定义的一种标准的参考,不同的车场有不同的定义,貌似没有统一。 在某宝上看到的ODB转db9的不同的线序: 1)1/2/3/6几个针脚都是一样的,分别上下针脚对应。 2)其中一种4/5/7/8也是上下对应的;另…

自动化处理,web自动化测试处理多窗口+切换iframe框架页总结(超细整理)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 web 自动化之处理…

APP外包开发的学习流程

学习iOS App的开发是一项有趣和富有挑战性的任务,是一个不断学习和不断进步的过程。掌握基础知识后,不断实践和尝试新的项目将使您的技能不断提升。下面和大家分享一些建议,可以帮助您开始学习iOS App的开发。北京木奇移动技术有限公司&#…

小红书 KOL 种草执行策略揭秘:打造爆款产品,提升品牌影响力

随着互联网的普及和社交媒体的发展,小红书成为了众多年轻人购物决策的重要参考平台。小红书 KOL 种草作为一种新兴的营销方式,以其强大的传播力和影响力,越来越受到各大品牌的重视。本文伯乐网络传媒将给大家深入探讨小红书 KOL 种草的执行策…

mysql转sqlite3

在项目中需要将mysql迁移到sqlite3中,此时需要作数据转换 准备工作 下载mysql2sqlite转换工具 https://github.com/dumblob/mysql2sqlite/archive/refs/heads/master.zip 下载sqlite3 https://www.sqlite.org/download.html 转换 命令行中输入如下命令 1、cd …

海康威视摄像头二次开发_云台控制_视频画面实时预览(基于Qt实现)

一、项目背景 需求:需要在公司的产品里集成海康威视摄像头的SDK,用于控制海康威视的摄像头。 拍照抓图、视频录制、云台控制、视频实时预览等等功能。 开发环境: windows-X64(系统) + Qt5.12.6(Qt版本) + MSVC2017_X64(使用的编译器) 海康威视提供了设备网络SDK,设备网…

Zabbix监控系统详解及配置

前言 作为一个运维,需要会使用监控系统查看服务器状态以及网站流量指标,利用监控系统的数据去了解上线发布的结果,和网站的健康状态。利用一个优秀的监控软件,我们可以: 通过一个友好的界面进行浏览整个网站所有的服务…

Data analysis|Tableau基本介绍及可实现功能

一、基础知识介绍 (一)什么是tableau tableau 成立于 2003 年,是斯坦福大学一个计算机科学项目的成果,该项目旨在改善分析流程并让人们能够通过可视化更轻松地使用数据。Tableau可以帮助用户更好地理解和发现数据中的价值&#x…

虚拟机centos7配置网络

虚拟机centos7配置网络 centos7克隆之后需要配置网络才能联网。 实验环境: VMware Workstation Pro 16CentOS 7系统虚拟机主机Windows 11系统 1.VMware网络模式设置为NAT模式 虚拟机–设置–网络适配器– ​​ ‍ 2.查看虚拟机 子网IP和网关IP 编辑–虚拟网…

一、Webpack相关(包括webpack-dev-server用以热更新和html-webpack-plugin)

概念与功能: webpack是前端项目工程化的具体解决方案。它提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览器端JavaScript的兼容性、性能优化等强大的功能。 快速上手:隔行变色 -S实际是--save的简写,表示安装的第三方…