Python Pandas - 合并/连接
Pandas - 合并和连接 DataFrame
Section titled “Pandas - 合并和连接 DataFrame”在数据分析中,组合来自不同来源的数据是一项常见任务。Pandas 提供了强大且灵活的工具,用于合并(merging)和连接(joining) DataFrame 对象,提供了类似于关系型数据库(如 SQL)的高性能内存操作。
基于共同列或索引组合 DataFrame 的主要函数是 pd.merge()。其基本签名如下:
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=('_x', '_y'), ...)主要参数说明:
left: 第一个DataFrame对象。right: 第二个DataFrame对象。how: 指定要执行的合并类型。选项包括:'inner'(默认)、'outer'、'left'、'right'。详见下文。on: 用于连接的列名。这些列必须存在于 两个DataFrame中。如果为None且未指定left_on/right_on,则在列的交集上进行合并。left_on: 用作连接键的 左侧DataFrame中的列名。right_on: 用作连接键的 右侧DataFrame中的列名。当连接键在两个DataFrame中名称不同时,使用left_on/right_on。left_index: 如果为True,使用 左侧DataFrame的索引作为连接键。right_index: 如果为True,使用 右侧DataFrame的索引作为连接键。sort: 如果为True(默认),则在结果中按字典顺序对连接键进行排序。设置为False可以显著提高性能。suffixes: 用于分别添加到左侧和右侧DataFrame中重叠列名(非 连接键)的字符串元组(tuple)。默认为('_x', '_y')。
让我们创建两个示例 DataFrame 来演示合并:
# 导入 pandas 库import pandas as pd
left = pd.DataFrame({ 'id': [1, 2, 3, 4, 5], 'Student_Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'], 'subject_id': ['sub1', 'sub2', 'sub4', 'sub6', 'sub5']})
right = pd.DataFrame({ 'id': [1, 2, 3, 4, 5], 'Teacher_Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'], 'subject_id': ['sub2', 'sub4', 'sub3', 'sub6', 'sub5']})
print("左侧 DataFrame:")print(left)print("\n右侧 DataFrame:")print(right)输出:
左侧 DataFrame: id Student_Name subject_id0 1 Alex sub11 2 Amy sub22 3 Allen sub43 4 Alice sub64 5 Ayoung sub5
右侧 DataFrame: id Teacher_Name subject_id0 1 Billy sub21 2 Brian sub42 3 Bran sub33 4 Bryce sub64 5 Betty sub5基于单个键列进行合并 (on)
Section titled “基于单个键列进行合并 (on)”如果两个 DataFrame 共享一个名称相同并用作键的列,请使用 on 参数。
import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 基于 'id' 列(两个表中都存在)进行合并merged_on_id = pd.merge(left, right, on='id')
print("基于 'id' 合并的 DataFrame:")print(merged_on_id)输出:
基于 'id' 合并的 DataFrame: id Student_Name subject_id_x Teacher_Name subject_id_y0 1 Alex sub1 Billy sub21 2 Amy sub2 Brian sub42 3 Allen sub4 Bran sub33 4 Alice sub6 Bryce sub64 5 Ayoung sub5 Betty sub5注意,subject_id 列在两个原始 DataFrame 中都存在,但不是连接键,它会自动获得后缀 _x(来自左侧)和 _y(来自右侧)。
基于多个键列进行合并 (on 与列表)
Section titled “基于多个键列进行合并 (on 与列表)”要基于多个列的组合进行合并,请将列名列表(list)传递给 on。
import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 仅在 'id' 和 'subject_id' 都匹配时进行合并merged_on_multiple = pd.merge(left, right, on=['id', 'subject_id'])
print("基于 'id' 和 'subject_id' 合并的 DataFrame:")print(merged_on_multiple)输出:
基于 'id' 和 'subject_id' 合并的 DataFrame: id Student_Name subject_id Teacher_Name0 4 Alice sub6 Bryce1 5 Ayoung sub5 Betty仅保留 left 和 right 中 id 和 subject_id 都相同的行(id=4, subject_id=‘sub6’ 和 id=5, subject_id=‘sub5’)。
理解合并类型 (how 参数)
Section titled “理解合并类型 (how 参数)”how 参数控制结果中包含哪些键,以及当键存在于一个 DataFrame 但不存在于另一个 DataFrame 时如何处理缺失值。
合并方法 (how) | SQL 对等操作 | 描述 |
|---|---|---|
'inner'(默认) | INNER JOIN | 仅保留在左侧和右侧 DataFrame 中 都 找到的键。键的交集。 |
'left' | LEFT OUTER JOIN | 保留左侧 DataFrame 中的 所有 键。如果某个键在右侧 DataFrame 中缺失,则将对应列填充 NaN。 |
'right' | RIGHT OUTER JOIN | 保留右侧 DataFrame 中的 所有 键。如果某个键在左侧 DataFrame 中缺失,则将对应列填充 NaN。 |
'outer' | FULL OUTER JOIN | 保留在左侧或右侧 DataFrame 中 任一 找到的 所有 键。对于在一个 DataFrame 中缺失的键,用 NaN 填充对应位置。键的并集。 |
让我们看看使用 subject_id 作为连接键的示例,该列在 left 和 right 中有不同的值。
左连接 (how='left')
Section titled “左连接 (how='left')”import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 保留来自 'left' 的所有 subject_id,与来自 'right' 的匹配left_join = pd.merge(left, right, on='subject_id', how='left')
print("基于 'subject_id' 的左连接:")print(left_join)输出:
基于 'subject_id' 的左连接: id_x Student_Name subject_id id_y Teacher_Name0 1 Alex sub1 NaN NaN # sub1 只存在于 left1 2 Amy sub2 1.0 Billy2 3 Allen sub4 2.0 Brian3 4 Alice sub6 4.0 Bryce4 5 Ayoung sub5 5.0 Betty来自 left 的所有 subject_id 值(sub1、sub2、sub4、sub6、sub5)都存在。由于 sub1 不存在于 right 中,因此该行来自 right 的列(id_y、Teacher_Name)为 NaN。
右连接 (how='right')
Section titled “右连接 (how='right')”import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 保留来自 'right' 的所有 subject_id,与来自 'left' 的匹配right_join = pd.merge(left, right, on='subject_id', how='right')
print("基于 'subject_id' 的右连接:")print(right_join)输出:
基于 'subject_id' 的右连接: id_x Student_Name subject_id id_y Teacher_Name0 2.0 Amy sub2 1 Billy1 3.0 Allen sub4 2 Brian2 NaN NaN sub3 3 Bran # sub3 只存在于 right3 4.0 Alice sub6 4 Bryce4 5.0 Ayoung sub5 5 Betty来自 right 的所有 subject_id 值(sub2、sub4、sub3、sub6、sub5)都存在。由于 sub3 不存在于 left 中,因此该行来自 left 的列(id_x、Student_Name)为 NaN。
外连接 (how='outer')
Section titled “外连接 (how='outer')”import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 保留来自 'left' 和 'right' 的所有 subject_idouter_join = pd.merge(left, right, on='subject_id', how='outer')
print("基于 'subject_id' 的外连接:")print(outer_join)输出:
基于 'subject_id' 的外连接: id_x Student_Name subject_id id_y Teacher_Name0 1.0 Alex sub1 NaN NaN # 只在 left 中1 2.0 Amy sub2 1.0 Billy2 3.0 Allen sub4 2.0 Brian3 4.0 Alice sub6 4.0 Bryce4 5.0 Ayoung sub5 5.0 Betty5 NaN NaN sub3 3.0 Bran # 只在 right 中来自两个 DataFrame 的所有唯一 subject_id 值(sub1、sub2、sub3、sub4、sub5、sub6)都包含在内。当一个 subject ID 存在于一个 DataFrame 但不存在于另一个 DataFrame 时,对应位置会出现 NaN 值。
内连接 (how='inner')
Section titled “内连接 (how='inner')”默认行为(how='inner')仅保留在 两个 DataFrame 中都存在的键。
import pandas as pd# (使用上面定义的 left 和 right DataFrame)
# 仅保留 'left' 和 'right' 中都存在的 subject_idinner_join = pd.merge(left, right, on='subject_id', how='inner')# 等效于: inner_join = pd.merge(left, right, on='subject_id')
print("基于 'subject_id' 的内连接:")print(inner_join)输出:
基于 'subject_id' 的内连接: id_x Student_Name subject_id id_y Teacher_Name0 2 Amy sub2 1 Billy1 3 Allen sub4 2 Brian2 4 Alice sub6 4 Bryce3 5 Ayoung sub5 5 Betty仅出现 subject_id 值 sub2、sub4、sub5、sub6,因为这些是仅在 left 和 right DataFrame 中都找到的值。
除了 pd.merge() 外,Pandas 还提供了 DataFrame.join() 方法,它方便用于基于 DataFrame 索引进行连接,或将一个 DataFrame 的索引与另一个 DataFrame 的列进行连接。pd.concat() 是另一个相关函数,用于垂直或水平堆叠 DataFrame。然而,pd.merge() 是基于共同值组合 DataFrame 的最通用且类似 SQL 的函数。