大数跨境
0
0

一文精通 pandas merge

一文精通 pandas merge 数据分析学习与实践
2023-06-02
0
导读:merge 全面的实用指南 Merge 能够将来自不同来源的数据组合成一个统一的结构。在处理表格数据时,这是

merge 全面的实用指南

Merge 能够将来自不同来源的数据组合成一个统一的结构。在处理表格数据时,这是一个必不可少的操作,因为将所有数据存储大多都。

了解如何在Pandas中有效地合并DataFrame是任何数据科学家或分析师的一项重要技能。

Merge 意味着根据相同列中的值合并DataFrame。

合并DataFrames示意图.png

在这篇文章中,我们将通过一组全面的20个例子,来阐明合并操作的细微差别。我们将从基本的合并功能开始,逐步深入到更复杂的场景中,涵盖所有关于用Pandas合并DataFrames的细节。

我们将涉及的函数是:

  • merge
  • merge_asof
  • merge_ordered

让我们先创建两个DataFrames,在例子中使用。

import numpy as np  
import pandas as pd  
  
  
names = pd.DataFrame(   
 {  
 "id": [123410],  
 "name": ["Emily""Jane""Joe""Matt""Lucas"],  
 "age": np.random.randint(2030, size=5)  
 }  
  
)  
  
scores = pd.DataFrame(  
 {  
 "id": np.arange(18),  
 "score": np.random.randint(80100, size=7),  
 "class": list("ABCAACA")  
 }  
)

namesscores DataFrame

示例 1

merge 函数的基本语法如下。参数 "on"表示在关联行时要使用的列。

merged_df = names.merge(scores, on="id")

示例 2--参数

有不同的合并类型。how参数从以下类型中定义它:

  • left: 只使用左边数据框架中的键值
  • right:只使用右边数据框架中的键值
  • outer:使用两个数据框架的键的联合。
  • inner:使用两个数据框架的键的得到交集
  • cross:使用两个数据框架的笛卡尔乘积。

how参数的默认值是inner,所以在前面的例子中,合并后的DataFrame包含一个键的交集。

键值是用on参数指定的列中的值。

让我们做一个left的合并。

merged_df = names.merge(scores, on="id", how="left")

合并后的数据框架包括左边数据框架的所有键。不匹配的行用 "NaN"填充,即标准的缺失值。

示例 3--右合并

它与左合并相反,但我不建议使用右合并,因为它可以通过改变DataFrame的顺序和使用左合并来实现。

merged_df = names.merge(scores, on="id", how="left")
merged_df = scores.merge(names, on="id", how="right")

示例 4-- 外(outer)合并

merged_df = names.merge(scores, on="id", how="outer")

合并后的数据框架包括两个数据框架的所有 key。

示例 5 -- 指标参数(indicator)

"indicator"参数在合并后的数据框架中创建一个列,指示行中的关键值来自哪里。

  • both: 每行中对应的 key 值存在于两个源数据框架中
  • left_only:  每行中对应的 key 值只存在原左边的数据框
  • right_only: 每行中对应的 key 值只存在原右边的数据框
merged_df = names.merge(scores, on="id", how="outer", indicator=True)

示例 6 -- 指示器参数

indicator参数也是以字符串值为参数,作为合并后指示列的名称。

merged_df = names.merge(scores, on="id", how="left", indicator="source")

示例 7 -- left_on和right_on参数

如果用于合并DataFrames的列有不同的名字,我们可以使用left_onright_on参数。使用场景两个源dataframe的 key 的列名有差异。如,表1中为 id,表2中为 id_number

scores = scores.rename(columns={"id""id_number"})
merged_df = names.merge(scores, left_on="id", right_on="id_number")

示例 8 --多列合并

我们将为这个例子创建两个新的DataFrames。适用场景为多 key 进行关联。

products = pd.DataFrame({"pg": ["A""A""A""B""B""B"], 
       "id": [101102103101102104],     
       "price": np.random.randint(5080, size=6),
       "cost": np.random.randint(4050, size=6),
       "discount": [0.10.1000.20]    }    )
sales = pd.DataFrame({ "pg": ["A""A""A""B""B""B"],
       "id": [101102105101102106], 
       "sales_qty": np.random.randint(110, size=6),        "discount": [00.10.10.200]    }    )

为了合并多列的DataFrames,我们把列名写成一个Python list。

merged_df = products.merge(sales, on=["pg""id"])

示例 9 -- suffixes参数

用于标记两个dataframe中同名的字段,

在前面的例子中,合并后的DataFrame有discount_xdiscount_y两列。x和y的后缀是用来分隔两个DataFrame中存在的同名列的。x用于左边的数据框架,y用于右边的数据框架。

我们可以使用自定义后缀来使输出更容易理解。

merged_df = products.merge(sales, on=["pg""id"], suffixes=["_products""_sales"])

示例 10 -- 多列

就像on参数一样, right_onleft_on参数在有不同列名的情况下使用一个列表作为参数。

sales = sales.rename(columns={"id""product_id"})
merged_df = products.merge(sales,
         left_on=["pg""id"],
         right_on = ["pg","product_id"],
         how="left",
         suffixes=["_products""_sales"])

示例 11 -- 根据索引合并

我们也可以根据索引值合并DataFrames。我们将为这个例子创建两个新的DataFrames。

df1 = pd.DataFrame(np.random.randint(010, size=(54)),
       columns=list("ABCD"))
df2 = pd.DataFrame(np.random.randint(010, size=(54)),
       columns=list("EFGH"), index=[23456])

正如我们在上面的截图中看到的,DataFrames有不同的索引值。一个从0开始,另一个从2开始。

为了合并索引,我们使用left_indexright_index参数。

merged_df = df1.merge(df2, left_index=True, right_index=True)

由于我们使用了inner合并,合并后的DataFrame只包括两个DataFrame中存在的index。

示例12 -- how参数与索引的合并

在对索引进行合并时,我们也可以使用how参数。

merged_df = df1.merge(df2, left_index=True, right_index=True, how="left")

示例13 -- 合并时间序列数据

时间序列数据可能包括在非常短的时间段内进行的测量(例如,在秒级)。因此,当我们合并两个由时间序列数据组成的DataFrames时,我们可能会遇到测量值偏离一到两秒的情况。

对于这种情况,Pandas通过merge_asof函数提供了一种 "智能"的合并方式。

假设我们正在合并数据框A和B。如果左边数据框中的某一行在右边数据框中没有匹配的行,merge_asof允许取一个值与左边数据框中的值接近的行。

这类似于左合并,只是我们在最接近的键上进行匹配,而不是相等的键。两个数据框架都必须按键进行排序。

对于左边DataFrame中的每一行:

  • backward 搜索右边数据框中"on"键小于或等于左边的键,选择key值最近的值
  • forward 搜索右边数据框中"on"键大于或等于左边的键,选择key值最近的值
  • nearest 搜索选择右边DataFrame中 "on"键与左边键的绝对距离最近的一行。

让我们创建两个包含时间序列数据的新DataFrame。

df1 = pd.DataFrame(   
 {  
 "time": pd.date_range(start="2022-12-09", periods=7, freq="2S"),  
 "left_value": np.round(np.random.random(7), 2)  
 } 
)  
  
df2 = pd.DataFrame(  
 {  
 "time": pd.date_range(start="2022-12-09", periods=6, freq="3S"),  
 "right_value": np.round(np.random.random(6), 2)  
 }  
)

时间栏中的一些数值是重叠的,而另一些则相差几秒钟。

让我们看看当我们合并它们时会发生什么。默认是backward

merged_df = pd.merge_asof(df1, df2, on="time")
  1. 右边的数据框架(df2)没有00:00:02的值,所以在合并的数据框架中,00:00:00的值被作为右边的值。
  2. 右边的数据框架(df2)没有00:00:04的值,所以在合并的数据框架中,00:00:03的值被作为右边的值。

示例14 -- 方向(direction)参数

在前面的例子中,merge_asof函数为不匹配的行寻找之前的值,因为方向参数的默认值是 "backward"。

让我们把它改为 "nearest",看看会发生什么。

merged_df = pd.merge_asof(df1, df2, on="time", direction="nearest")

第一行的右边数值是0.36,因为下一个数值(00:00:03)比前一个数值(00:00:00)更接近左边DataFrame中的数值(00:00:02)。

示例15 -- 公差(tolerance)参数

我们还可以设置一个公差,在检查前一个和后一个值时使用。

在下面的例子中,方向是向前的,所以下一个值会被检查为不匹配的行。我们还设置了一个1秒的容差,因此,为了使用下一个值,它最多偏离1秒。

merged_df = pd.merge_asof(  
      df1,  
      df2,  
      on="time",  
      direction="forward",  
      tolerance=pd.Timedelta("1s")  
)

看看合并后的DataFrame中的第三和第六行。右边的值是 "NaN",因为右边DataFrame中的下一个值在这些行中偏离了2秒。

  • 左边:00:00:04,右边的下一个值:00:00:06
  • 左边:00:00:10,右边的下一个值:00:00:12

示例16 -- allow_exact_matches参数

我们还可以选择不允许在合并后的数据框架中出现精确匹配。默认情况下,精确匹配适用于合并数据框,但可以使用 "allow_exact_matches"参数来改变。on 条件只选 小于或大于,不关联等于。

merged_df = pd.merge_asof(df1, df2, on="time", allow_exact_matches=False)

第一行的时间值是相同的,但是合并后的DataFrame在第一行的右边值栏有一个NaN值,因为我们把allow_exact_matches参数的值设置为False。

示例17 -- by参数

在合并数据点时,"by"参数可用于将组与上一个或下一个值分开。

让我们给我们的DataFrames添加一个组列。

df1["group"] = ["AA"] * 4 + ["BB"] * 3
df2["group"] = ["AA"] * 3 + ["BB"] * 3

示例18 - 有序合并

merge_ordered函数对有序数据进行合并,可选择填充/插值。它是为诸如时间序列等有序数据设计的。

通过一个例子可以更容易地理解它:

merged_df = pd.merge_asof(df1, df2, on="time", by="group")

BB组第一行的右边数值是NaN。我们是根据 "backward"的方向进行合并的,而且前一个值属于不同的组。

示例18 -- 有序合并(merge_ordered)

merge_ordered 函数对有序数据进行合并,可选择填充/插值。它是为诸如时间序列等有序数据设计的。

通过一个例子可以更容易地理解它:

merged_df = pd.merge_ordered(df1, df2)

这些行是按时间列排序的。如果其中一个DataFrame没有特定的时间值,那么来自该DataFrame的列将被填充为NaN

示例19 - fill_method参数

当使用merge_ordered进行有序合并时, 我们可以使用fill_method参数来定义一个插值方法。

默认值是NaN,我们唯一可以使用的选项是 "ffill",意思是向前填充。

merged_df = pd.merge_ordered(df1, df2, fill_method="ffill")

将输出结果与前面的例子进行比较,你会注意到NaN值是如何被替换成以前的值的。

示例 20 -- left_by 参数

我们也可以在每个组内分别进行有序合并。参数 "left_by "按组列将左边的DataFrame分组,并与右边的DataFrame逐个合并。

merged_df = pd.merge_ordered(df1, df2, fill_method="ffill", left_by="group")

与前面的例子不同,"BB "组第一行的右边数值是NaN,因为我们不能使用其他组的数值。

最后的话

通过这20个例子,我们已经探索了各种合并场景,从最简单的到更复杂的。有了这些实用的例子,你就可以准备好应对任何合并任务了。


【声明】内容源于网络
0
0
数据分析学习与实践
数据分析,数据科学,线性代数,统计学,AI,python,可视化,excel
内容 343
粉丝 0
数据分析学习与实践 数据分析,数据科学,线性代数,统计学,AI,python,可视化,excel
总阅读65
粉丝0
内容343