merge笛卡尔乘积

365 阅读4分钟

确实,关联列中有重复值的情况在合并操作中是非常重要的一种情况,通常会导致“笛卡尔积”式的合并,也就是 多对一一对多 的连接。这是由于 pandas.merge() 在执行合并时会根据两个表中键列的匹配情况,生成所有可能的配对。

1. 当左表(df1)的关联列有重复值时

假设我们有一个左表(df1)的关联列有重复值,右表(df2)中的关联列是唯一的,合并时左表的每个重复键都会与右表的对应行进行合并,产生多个匹配行。

示例:

import pandas as pd

# 左表(df1)
df1 = pd.DataFrame({
    'A': [1, 1, 2],
    'B': ['X', 'Y', 'Z']
})

# 右表(df2)
df2 = pd.DataFrame({
    'A': [1, 2],
    'C': ['P', 'Q']
})

# 合并:左表的 'A' 列有重复值
result = pd.merge(df1, df2, on='A', how='inner')

print(result)
输出:
   A  B  C
0  1  X  P
1  1  Y  P
2  2  Z  Q

解释:

  • 左表(df1A=1 有两个重复值(XY)。
  • 右表(df2A=1 对应的是 C=P,因此左表中的每一行(A=1)都会与右表的这一行进行合并,生成两个结果。
  • 对于 A=2,它只在右表中有一个匹配行,因此合并后就只出现一行。

2. 当右表(df2)的关联列有重复值时

如果右表的关联列有重复值,左表中的每一行也会与右表中的每一个重复值行进行合并,生成多个匹配行。

示例:

# 左表(df1)
df1 = pd.DataFrame({
    'A': [1, 2],
    'B': ['X', 'Y']
})

# 右表(df2)
df2 = pd.DataFrame({
    'A': [1, 1, 2],
    'C': ['P', 'Q', 'R']
})

# 合并:右表的 'A' 列有重复值
result = pd.merge(df1, df2, on='A', how='inner')

print(result)
输出:
   A  B  C
0  1  X  P
1  1  X  Q
2  2  Y  R

解释:

  • 右表(df2A=1 有两个重复值(PQ)。
  • 左表(df1A=1 只有一行,因此左表中的这行会与右表中的两个匹配行(PQ)合并,产生两个结果。
  • 对于 A=2,它只在右表中有一个匹配行(R),因此合并后就只出现一行。

3. 当左表和右表的关联列都有重复值时

如果 左表和右表 的关联列都有重复值,那么合并时就会产生更多的匹配行,形成一个“笛卡尔积”的效果,即每个左表的重复行都会与右表的重复行进行所有可能的配对。

示例:

# 左表(df1)
df1 = pd.DataFrame({
    'A': [1, 1, 2],
    'B': ['X', 'Y', 'Z']
})

# 右表(df2)
df2 = pd.DataFrame({
    'A': [1, 1, 2],
    'C': ['P', 'Q', 'R']
})

# 合并:左表和右表的 'A' 列都有重复值
result = pd.merge(df1, df2, on='A', how='inner')

print(result)
输出:
   A  B  C
0  1  X  P
1  1  X  Q
2  1  Y  P
3  1  Y  Q
4  2  Z  R

解释:

  • 左表(df1A=1 有两个重复值(XY),右表(df2A=1 也有两个重复值(PQ)。
  • 由于左表和右表中的 A=1 都有重复,合并时会进行所有可能的组合:XPXQYPYQ,从而生成 4 行。
  • 对于 A=2,它在左表和右表中都只有一个匹配,因此合并后只出现一行。

4. 笛卡尔积(cross join

当两个表中的关联列都是无关列时,可以生成 笛卡尔积(cross join)pandas 直到最近的版本才支持通过 how='cross' 参数进行笛卡尔积合并。

示例(how='cross'):

# 左表(df1)
df1 = pd.DataFrame({
    'A': [1, 2],
    'B': ['X', 'Y']
})

# 右表(df2)
df2 = pd.DataFrame({
    'C': ['P', 'Q']
})

# 笛卡尔积:左表与右表进行笛卡尔积
result = pd.merge(df1, df2, how='cross')

print(result)
输出:
   A  B  C
0  1  X  P
1  1  X  Q
2  2  Y  P
3  2  Y  Q

解释:

  • 笛卡尔积:左表(df1)有两行,右表(df2)有两行,所以每一行都将与另一表的每一行进行组合,结果生成四行。

总结

  • 多对一连接:如果左表的关联列有重复值,但右表中的值是唯一的,合并时左表中的每个重复值都会与右表中的匹配行进行合并,生成多个结果。
  • 一对多连接:如果右表的关联列有重复值,但左表中的值是唯一的,合并时右表中的每个重复值都会与左表中的匹配行进行合并,生成多个结果。
  • 多对多连接:如果左表和右表中的关联列都有重复值,那么合并时会进行笛卡尔积式的组合,即每个左表的重复行都会与右表的重复行进行所有可能的配对。
  • 笛卡尔积(cross join) :如果不使用任何关联列(即无条件连接),可以使用 how='cross' 生成笛卡尔积。