You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataFrame中匹配两列并按Col1首值分组生成Col3

解决DataFrame中关联链统一Col3值的问题

问题描述

给定一个DataFrame,需要比较Col1和Col2列,当记录间存在关联匹配时(例如行2的LG Premier出现在行1的Col2,行3的S Premier出现在行2的Col2),将Col3统一设置为该关联链中Col1的首个值。

示例输入DataFrame:

|Col1        |Col2       |cnt   |
1 |Premier     | LG Premier|3     | 
2 |LG Premier  | S Premier |3     |
3 |K Premier   | S Premier |3     |
4 |Dell        | Dell ABC  |2     |
5 |Dell ABC    | Dell GBC  |2     |

预期输出DataFrame:

|Col1        |Col2       |cnt   |Col3       |
1 |Premier     | LG Premier|3     |Premier    |
2 |LG Premier  | S Premier |3     |Premier    |
3 |K Premier   | S Premier |3     |Premier    |  
4 |Dell        | Dell ABC  |2     |Dell       |
5 |Dell ABC    | Dell GBC  |2     |Dell       |

关联逻辑:行1的Col3设为Premier;行2因LG Premier出现在行1的Col2,Col3设为Premier;行3因S Premier出现在行2的Col2,Col3设为Premier。


解决思路

这个问题本质是图的连通分量查找:将Col1和Col2中的每个唯一值视为图的节点,每一行的Col1和Col2之间建立一条边,这样关联的记录就会属于同一个连通分量。之后,为每个连通分量找到最早出现的Col1值,将其作为该分量所有行的Col3值。

我们可以用两种方式实现:使用networkx库快速构建图并查找连通分量,或者手动实现并查集(DSU)结构。


方法一:使用NetworkX库实现

import pandas as pd
import networkx as nx

# 构造示例数据
data = {
    'Col1': ['Premier', 'LG Premier', 'K Premier', 'Dell', 'Dell ABC'],
    'Col2': ['LG Premier', 'S Premier', 'S Premier', 'Dell ABC', 'Dell GBC'],
    'cnt': [3, 3, 3, 2, 2]
}
df = pd.DataFrame(data)

# 构建图
G = nx.Graph()
# 添加所有唯一值作为节点
all_values = pd.concat([df['Col1'], df['Col2']]).unique()
G.add_nodes_from(all_values)
# 为每一行的Col1和Col2添加边
for _, row in df.iterrows():
    G.add_edge(row['Col1'], row['Col2'])

# 查找所有连通分量
components = list(nx.connected_components(G))

# 为每个连通分量确定首个Col1值
component_root = {}
for comp in components:
    # 找到该分量中最早出现的Col1对应的行
    mask = df['Col1'].isin(comp)
    first_row_idx = mask[mask].index.min()
    root_val = df.loc[first_row_idx, 'Col1']
    # 将分量内所有值映射到该根值
    for val in comp:
        component_root[val] = root_val

# 生成Col3列
df['Col3'] = df['Col1'].map(component_root)

print(df)

方法二:手动实现并查集(DSU)

如果不想依赖第三方库,可以手动实现并查集来管理连通分量:

import pandas as pd

class DSU:
    def __init__(self):
        self.parent = {}
    
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, x, y):
        if x not in self.parent:
            self.parent[x] = x
        if y not in self.parent:
            self.parent[y] = y
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x != root_y:
            self.parent[root_y] = root_x

# 构造示例数据
data = {
    'Col1': ['Premier', 'LG Premier', 'K Premier', 'Dell', 'Dell ABC'],
    'Col2': ['LG Premier', 'S Premier', 'S Premier', 'Dell ABC', 'Dell GBC'],
    'cnt': [3, 3, 3, 2, 2]
}
df = pd.DataFrame(data)

# 初始化并查集并合并关联节点
dsu = DSU()
for _, row in df.iterrows():
    dsu.union(row['Col1'], row['Col2'])

# 映射每个值到其连通分量的根
all_values = pd.concat([df['Col1'], df['Col2']]).unique()
root_map = {val: dsu.find(val) for val in all_values}

# 为每个根确定对应的首个Col1值
root_to_first_col1 = {}
for root in set(root_map.values()):
    # 获取当前连通分量的所有值
    component_vals = [val for val, r in root_map.items() if r == root]
    # 找到最早出现的Col1行
    mask = df['Col1'].isin(component_vals)
    first_row_idx = mask[mask].index.min()
    root_to_first_col1[root] = df.loc[first_row_idx, 'Col1']

# 生成Col3列
df['Col3'] = df['Col1'].apply(lambda x: root_to_first_col1[root_map[x]])

print(df)

输出结果

两种方法都会得到预期的输出:

Col1        Col2  cnt     Col3
0     Premier   LG Premier    3  Premier
1  LG Premier   S Premier    3  Premier
2  K Premier   S Premier    3  Premier
3        Dell    Dell ABC    2     Dell
4    Dell ABC    Dell GBC    2     Dell

内容的提问来源于stack exchange,提问作者Kiki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:41:44