WEBKT

Pandas merge() 函数详解: 连接你的数据,玩转数据世界的魔术师

8 0 0 0

Pandas merge() 函数详解: 连接你的数据,玩转数据世界的魔术师

1. 为什么需要 merge()?

2. merge() 函数的基本用法

2.1 举个例子: 简单的 merge()

3. how 参数: 连接方式详解

3.1 inner 连接 (内连接)

3.2 left 连接 (左连接)

3.3 right 连接 (右连接)

3.4 outer 连接 (外连接)

4. on, left_on, right_on 参数: 指定连接键

5. 多列连接

6. 处理重复列名

7. 在不同场景下如何选择连接方式

8. 实战案例: 电商数据分析

9. 总结

10. 进阶技巧: 性能优化

11. 常见问题及解答

Pandas merge() 函数详解: 连接你的数据,玩转数据世界的魔术师

嘿,码农小伙伴们!

在数据分析的浩瀚海洋里,Pandas 是我们手中的利器。今天,咱们就来聊聊 Pandas 里一个超好用的函数—— merge(),它是我们处理多个数据表时,连接数据的得力助手。就像拼图一样,merge() 可以把分散的数据碎片拼凑成一个完整的数据集,方便我们进行后续的分析和挖掘。

1. 为什么需要 merge()

在实际工作中,我们经常会遇到数据分散在多个表格里的情况。比如,用户数据可能在一个表里,订单数据在另一个表里,商品信息又在单独的一个表里。如果想分析用户购买了哪些商品,或者哪些商品卖得最好,就需要把这些表连接起来。merge() 函数就是用来干这个的,它就像一个智能的连接器,根据你指定的条件,把不同的表格合并成一个。

2. merge() 函数的基本用法

merge() 函数的基本语法是这样的:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, ...)

别被这一长串参数吓到,其实最常用的就那么几个:

  • left: 左侧的 DataFrame,也就是你要合并的第一个表格。
  • right: 右侧的 DataFrame,也就是你要合并的第二个表格。
  • how: 连接方式,后面会详细介绍。 innerleftrightouter 四种连接方式,控制着如何合并数据。
  • on: 用于连接的列名,如果两个表里都有相同的列名,就用它。 相当于告诉 merge(),这两个表要根据哪一列来连接。
  • left_on: 左侧 DataFrame 中用于连接的列名,当左右两个表用于连接的列名不一样的时候,可以使用它。
  • right_on: 右侧 DataFrame 中用于连接的列名, 当左右两个表用于连接的列名不一样的时候,可以使用它。

2.1 举个例子: 简单的 merge()

假设我们有两个表:用户表订单表

用户表 (user_df):

用户ID 用户名 城市
1 张三 北京
2 李四 上海
3 王五 广州

订单表 (order_df):

订单ID 用户ID 商品名称 金额
101 1 苹果 10
102 2 香蕉 5
103 1 橘子 8

现在,我们想把用户表订单表合并起来,以便查看每个用户的订单信息。 这两个表都有一个共同的列 用户ID,我们可以用它来连接这两个表。

import pandas as pd
# 创建用户表
user_data = {'用户ID': [1, 2, 3], '用户名': ['张三', '李四', '王五'], '城市': ['北京', '上海', '广州']}
user_df = pd.DataFrame(user_data)
# 创建订单表
order_data = {'订单ID': [101, 102, 103], '用户ID': [1, 2, 1], '商品名称': ['苹果', '香蕉', '橘子'], '金额': [10, 5, 8]}
order_df = pd.DataFrame(order_data)
# 使用 merge() 连接两个表
merged_df = pd.merge(order_df, user_df, on='用户ID', how='inner')
print(merged_df)

输出结果:

订单ID 用户ID 商品名称 金额 用户名 城市
0 101 1 苹果 10 张三 北京
1 103 1 橘子 8 张三 北京
2 102 2 香蕉 5 李四 上海

看到了吗?merge() 函数根据 用户ID 把两个表连接起来了,现在我们可以看到每个订单对应的用户信息了。

3. how 参数: 连接方式详解

how 参数是 merge() 函数的核心,它决定了如何连接两个表,主要有四种连接方式:innerleftrightouter

3.1 inner 连接 (内连接)

  • 定义: inner 连接是默认的连接方式。 它只保留两个表中,on 列的值都匹配的行。
  • 特点: 最终结果是两个表的交集。 如果某个 用户ID订单表里,但不在用户表里,那么这个订单的信息就会被丢弃。
  • 场景: 适用于需要找到两个表共同信息的情况。

例子 (使用上面的 用户表订单表):

merged_df_inner = pd.merge(order_df, user_df, on='用户ID', how='inner')
print(merged_df_inner)

输出结果和前面的例子一样。

3.2 left 连接 (左连接)

  • 定义: left 连接会保留左侧表left 参数指定的表)的所有行,以及右侧表中与左侧表 on 列匹配的行。 如果右侧表没有匹配的行,那么对应的列会用 NaN (缺失值) 填充。
  • 特点: 结果至少包含左侧表的所有行。 相当于以左侧表为主,将右侧表的信息合并过来。
  • 场景: 适用于需要保留左侧表的所有信息,并尽可能地获取右侧表相关信息的情况。

例子:

假设我们新增一个用户,但这个用户还没有订单:

用户表 (user_df_new):

用户ID 用户名 城市
1 张三 北京
2 李四 上海
3 王五 广州
4 赵六 深圳
import pandas as pd
# 创建用户表
user_data = {'用户ID': [1, 2, 3, 4], '用户名': ['张三', '李四', '王五', '赵六'], '城市': ['北京', '上海', '广州', '深圳']}
user_df_new = pd.DataFrame(user_data)
# 创建订单表
order_data = {'订单ID': [101, 102, 103], '用户ID': [1, 2, 1], '商品名称': ['苹果', '香蕉', '橘子'], '金额': [10, 5, 8]}
order_df = pd.DataFrame(order_data)
# 使用 left 连接
merged_df_left = pd.merge(order_df, user_df_new, on='用户ID', how='left')
print(merged_df_left)

输出结果:

订单ID 用户ID 商品名称 金额 用户名 城市
0 101 1 苹果 10 张三 北京
1 102 2 香蕉 5 李四 上海
2 103 1 橘子 8 张三 北京

即使用户ID为 4 的赵六在订单表里没有订单信息,使用left连接,也会保留他的用户信息,而他的订单信息列将会是 NaN

3.3 right 连接 (右连接)

  • 定义: right 连接和 left 连接相反,它会保留右侧表right 参数指定的表)的所有行,以及左侧表中与右侧表 on 列匹配的行。 如果左侧表没有匹配的行,对应的列会用 NaN 填充。
  • 特点: 结果至少包含右侧表的所有行。 相当于以右侧表为主,将左侧表的信息合并过来。
  • 场景: 适用于需要保留右侧表的所有信息,并尽可能地获取左侧表相关信息的情况。

例子:

还是用上面的用户表订单表,我们反过来连接:

import pandas as pd
# 创建用户表
user_data = {'用户ID': [1, 2, 3], '用户名': ['张三', '李四', '王五'], '城市': ['北京', '上海', '广州']}
user_df = pd.DataFrame(user_data)
# 创建订单表
order_data = {'订单ID': [101, 102, 103, 104], '用户ID': [1, 2, 1, 5], '商品名称': ['苹果', '香蕉', '橘子', '葡萄'], '金额': [10, 5, 8, 12]}
order_df_new = pd.DataFrame(order_data)
# 使用 right 连接
merged_df_right = pd.merge(user_df, order_df_new, on='用户ID', how='right')
print(merged_df_right)

输出结果:

用户ID 用户名 城市 订单ID 商品名称 金额
0 1 张三 北京 101 苹果 10.0
1 2 李四 上海 102 香蕉 5.0
2 1 张三 北京 103 橘子 8.0
3 5 NaN NaN 104 葡萄 12.0

我们看到,订单表用户ID 为 5 的用户,虽然在用户表中不存在,但是因为使用了 right 连接,所以该信息被保留了下来,用户名和城市显示为 NaN。 这展示了right连接的特性。

3.4 outer 连接 (外连接)

  • 定义: outer 连接会保留两个表的所有行。 对于无法匹配的行,用 NaN 填充缺失的列。
  • 特点: 结果是两个表的并集。 包含了两个表的所有信息,如果某些行在另一个表中不存在,那么对应的列会是 NaN
  • 场景: 适用于需要获取两个表的所有信息,并希望全面了解数据的情况。

例子:

import pandas as pd
# 创建用户表
user_data = {'用户ID': [1, 2, 3, 4], '用户名': ['张三', '李四', '王五', '赵六'], '城市': ['北京', '上海', '广州', '深圳']}
user_df_new = pd.DataFrame(user_data)
# 创建订单表
order_data = {'订单ID': [101, 102, 103, 104], '用户ID': [1, 2, 1, 5], '商品名称': ['苹果', '香蕉', '橘子', '葡萄'], '金额': [10, 5, 8, 12]}
order_df_new = pd.DataFrame(order_data)
# 使用 outer 连接
merged_df_outer = pd.merge(order_df_new, user_df_new, on='用户ID', how='outer')
print(merged_df_outer)

输出结果:

订单ID 用户ID 商品名称 金额 用户名 城市
0 101 1 苹果 10.0 张三 北京
1 103 1 橘子 8.0 张三 北京
2 102 2 香蕉 5.0 李四 上海
3 104 5 葡萄 12.0 NaN NaN
4 NaN 3 NaN NaN 王五 广州
5 NaN 4 NaN NaN 赵六 深圳

可以看到,outer连接保留了所有行。 订单表里用户ID为5的记录,以及用户表里用户ID为3和4的记录,都有保留,没有匹配到的信息用NaN填充。

4. on, left_on, right_on 参数: 指定连接键

  • on: 当两个表用于连接的列名完全相同时,使用 on 参数指定连接的列名。 这是最简单的情况。

    merged_df = pd.merge(df1, df2, on='key')  # 假设 df1 和 df2 都有名为 'key' 的列
    
  • left_onright_on: 当两个表用于连接的列名不一致时,需要使用 left_onright_on 参数来分别指定左侧和右侧表用于连接的列名。

    merged_df = pd.merge(df1, df2, left_on='key1', right_on='key2')  # df1 的 'key1' 列 和 df2 的 'key2' 列用于连接
    

例子: 列名不一致的情况

假设 用户表 的列名是 用户ID,而 订单表 的列名是 客户ID (为了说明问题,故意不一样):

用户表 (user_df):

用户ID 用户名 城市
1 张三 北京
2 李四 上海
3 王五 广州

订单表 (order_df):

订单ID 客户ID 商品名称 金额
101 1 苹果 10
102 2 香蕉 5
103 1 橘子 8
import pandas as pd
# 创建用户表
user_data = {'用户ID': [1, 2, 3], '用户名': ['张三', '李四', '王五'], '城市': ['北京', '上海', '广州']}
user_df = pd.DataFrame(user_data)
# 创建订单表
order_data = {'订单ID': [101, 102, 103], '客户ID': [1, 2, 1], '商品名称': ['苹果', '香蕉', '橘子'], '金额': [10, 5, 8]}
order_df = pd.DataFrame(order_data)
# 使用 left_on 和 right_on 连接
merged_df = pd.merge(order_df, user_df, left_on='客户ID', right_on='用户ID', how='inner')
print(merged_df)

输出结果:

订单ID 客户ID 商品名称 金额 用户ID 用户名 城市
0 101 1 苹果 10 1 张三 北京
1 103 1 橘子 8 1 张三 北京
2 102 2 香蕉 5 2 李四 上海

在这个例子中,我们使用 left_on='客户ID'right_on='用户ID' 指定了连接的列名,成功地将两个表连接起来了。

5. 多列连接

merge() 函数不仅可以根据一列连接,还可以根据多列进行连接。 只需要在 on, left_onright_on 参数中传入一个包含多个列名的列表即可。

例子: 根据多列连接

假设我们有两个表,一个表记录了用户的姓名和城市,另一个表记录了用户的姓名和地址邮编。 现在我们希望通过姓名和城市进行连接。

用户表 (user_df):

用户名 城市 爱好
张三 北京 篮球
李四 上海 游泳
张三 广州 足球

邮编表 (zip_df):

用户名 城市 邮编
张三 北京 100000
李四 上海 200000
王五 广州 510000
import pandas as pd
# 创建用户表
user_data = {'用户名': ['张三', '李四', '张三'], '城市': ['北京', '上海', '广州'], '爱好': ['篮球', '游泳', '足球']}
user_df = pd.DataFrame(user_data)
# 创建邮编表
zip_data = {'用户名': ['张三', '李四', '王五'], '城市': ['北京', '上海', '广州'], '邮编': [100000, 200000, 510000]}
zip_df = pd.DataFrame(zip_data)
# 使用多列连接
merged_df = pd.merge(user_df, zip_df, on=['用户名', '城市'], how='left')
print(merged_df)

输出结果:

用户名 城市 爱好 邮编
0 张三 北京 篮球 100000.0
1 李四 上海 游泳 200000.0
2 张三 广州 足球 NaN

在这个例子中,我们通过 on=['用户名', '城市'] 指定了根据 用户名城市 两列进行连接。 这样,只有当 用户名城市 都匹配的行才会被连接在一起。

6. 处理重复列名

当两个表连接后,如果存在相同的列名,merge() 函数会自动在列名后面添加后缀 _x_y 来区分它们, _x 表示来自左侧表, _y 表示来自右侧表。

例子: 处理重复列名

假设两个表都有 年龄 列,我们连接它们:

左侧表 (left_df):

用户名 年龄
张三 25
李四 30

右侧表 (right_df):

用户名 年龄
张三 26
王五 35
import pandas as pd
# 创建左侧表
left_data = {'用户名': ['张三', '李四'], '年龄': [25, 30]}
left_df = pd.DataFrame(left_data)
# 创建右侧表
right_data = {'用户名': ['张三', '王五'], '年龄': [26, 35]}
right_df = pd.DataFrame(right_data)
# 连接两个表
merged_df = pd.merge(left_df, right_df, on='用户名', how='left')
print(merged_df)

输出结果:

用户名 年龄_x 年龄_y
0 张三 25 26
1 李四 30 NaN

可以看到, 年龄 列被分成了 年龄_x年龄_y,分别代表来自左侧表和右侧表的年龄信息。

如果不想使用默认的后缀,可以使用 suffixes 参数自定义后缀。

merged_df = pd.merge(left_df, right_df, on='用户名', how='left', suffixes=('_left', '_right'))
print(merged_df)

输出结果:

用户名 年龄_left 年龄_right
0 张三 25 26
1 李四 30 NaN

7. 在不同场景下如何选择连接方式

选择合适的连接方式非常重要,这取决于你的数据分析需求。 下面是一些常见场景和推荐的连接方式:

  • 场景 1: 找出共同的信息

    • 需求: 你希望找到两个表中都存在的数据,例如,找出同时购买了 A 商品和 B 商品的用户。
    • 推荐: inner 连接。
  • 场景 2: 以一个表为主,补充另一个表的信息

    • 需求: 你有一个用户列表,想知道每个用户对应的订单信息。 即使某些用户没有订单,你也希望保留他们的信息。
    • 推荐: left 连接。 以用户表为左侧表,订单表为右侧表。
  • 场景 3: 以一个表为主,补充另一个表的信息,但希望看到所有信息

    • 需求: 你有订单列表,想知道每个订单对应的用户信息。 即使某些订单没有对应的用户,你仍然希望看到这些订单。
    • 推荐: right 连接。 以用户表为右侧表,订单表为左侧表。
  • 场景 4: 获取所有信息,并处理缺失值

    • 需求: 你想获取所有用户和所有订单的信息,并处理那些没有匹配到的数据。
    • 推荐: outer 连接。 如果数据量太大,可以考虑其他处理缺失值的方式。

8. 实战案例: 电商数据分析

假设我们是一家电商公司,我们有三个表格: 用户表订单表商品表

用户表 (users.csv):

用户ID,用户名,城市
1,张三,北京
2,李四,上海
3,王五,广州
4,赵六,深圳

订单表 (orders.csv):

订单ID,用户ID,商品ID,数量,下单时间
101,1,101,2,2023-01-10
102,2,102,1,2023-01-12
103,1,103,3,2023-01-15
104,3,101,1,2023-01-20

商品表 (products.csv):

商品ID,商品名称,价格
101,苹果,10
102,香蕉,5
103,橘子,8
104,葡萄,12

我们的目标是:

  1. 计算每个用户的总消费额。
  2. 统计每个商品的销售数量和总销售额。
  3. 分析每个城市的用户消费情况。
import pandas as pd
# 读取数据
users_df = pd.read_csv('users.csv')
orders_df = pd.read_csv('orders.csv')
products_df = pd.read_csv('products.csv')
# 1. 计算每个用户的总消费额
# 1. 将订单表和商品表连接,获取商品价格
order_product_df = pd.merge(orders_df, products_df, on='商品ID', how='left')
# 2. 计算每笔订单的消费额
order_product_df['消费额'] = order_product_df['数量'] * order_product_df['价格']
# 3. 将连接后的表和用户表连接
user_order_df = pd.merge(order_product_df, users_df, on='用户ID', how='left')
# 4. 计算每个用户的总消费额
user_total_cost = user_order_df.groupby('用户名')['消费额'].sum().reset_index()
print('每个用户的总消费额:
', user_total_cost)
# 2. 统计每个商品的销售数量和总销售额
# 1. 将订单表和商品表连接
order_product_df = pd.merge(orders_df, products_df, on='商品ID', how='left')
# 2. 计算每笔订单的消费额
order_product_df['消费额'] = order_product_df['数量'] * order_product_df['价格']
# 3. 统计每个商品的销售数量和总销售额
product_sales = order_product_df.groupby('商品名称').agg({'数量': 'sum', '消费额': 'sum'}).reset_index()
print('\n每个商品的销售数量和总销售额:
', product_sales)
# 3. 分析每个城市的用户消费情况
# 1. 将订单表和商品表连接,获取商品价格
order_product_df = pd.merge(orders_df, products_df, on='商品ID', how='left')
# 2. 计算每笔订单的消费额
order_product_df['消费额'] = order_product_df['数量'] * order_product_df['价格']
# 3. 将连接后的表和用户表连接
user_order_df = pd.merge(order_product_df, users_df, on='用户ID', how='left')
# 4. 统计每个城市的总消费额
city_total_cost = user_order_df.groupby('城市')['消费额'].sum().reset_index()
print('\n每个城市的用户消费情况:
', city_total_cost)

在这个案例中,我们使用了多次 merge() 函数,通过 left 连接和 left 连接,把多个表连接起来,获取了我们需要的分析数据。

9. 总结

merge() 函数是 Pandas 中非常重要的一个工具,它能帮助我们高效地连接和处理多个数据表。 通过掌握 how 参数的不同选项,以及 on, left_on, right_on 参数的用法,你就能灵活地应对各种数据连接的需求。 记住,多加练习,才能熟练掌握! 希望这篇文章对你有所帮助! 如果你有任何问题,欢迎随时提问! 祝你数据分析之旅愉快!

10. 进阶技巧: 性能优化

当处理大型数据集时,merge() 函数的性能可能会成为瓶颈。 以下是一些优化技巧:

  • 选择合适的连接方式: 尽量选择最合适的连接方式,避免不必要的 outer 连接。
  • 索引: 如果连接键是 DataFrame 的索引,merge() 函数的性能会更好。 可以使用 set_index() 方法将列设置为索引。
  • 数据类型: 确保连接键的数据类型一致。 如果数据类型不一致,merge() 函数需要进行类型转换,这会降低性能。
  • 使用 pd.concat(): 如果只是简单地将两个 DataFrame 堆叠在一起(例如,增加行),pd.concat() 通常比 merge() 更快。
  • 避免不必要的连接: 在进行 merge() 之前,尽量过滤掉不需要的行或列,减少数据量。

11. 常见问题及解答

  • Q: 为什么我的 merge() 连接结果不对?

    • A: 检查以下几点:
      • 确认连接的列名是否正确。 on, left_on, right_on 参数是否正确设置。
      • 检查连接的列的数据类型是否一致。
      • 确认你选择了正确的连接方式 ( inner, left, right, outer )。 根据你的需求,选择最合适的连接方式。
      • 检查是否有重复的列名。 如果有,使用 suffixes 参数自定义后缀,或者在连接之前重命名列名。
  • Q: 我的 merge() 运行速度很慢,怎么办?

    • A: 参考 10. 进阶技巧:性能优化 中的建议。 尝试优化你的代码,例如,使用索引、调整数据类型、选择更合适的连接方式等。
  • Q: 我可以使用 merge() 连接超过两个表吗?

    • A: 可以。 你可以使用链式 merge(), 例如:merged_df = pd.merge(pd.merge(df1, df2, ...), df3, ...), 或者使用循环。 但是,当表很多时,代码可能会变得复杂,建议考虑使用其他工具,比如数据库。

希望这些能帮助你更好地理解和使用 merge() 函数! 祝你编码愉快!

码神老李 pandasmerge数据分析Python

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8779