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

求助:Pandas中基于ID元组元素交集的分组实现方法

基于连通分量的Pandas分组方案(按元组元素交集分组)

问题分析

你需要的不是按元组完全匹配分组,而是将存在元素交集的元组归为同一组——这本质是图论中的连通分量问题:把每个唯一元组看作节点,若两个元组有公共元素则连边,最终每个连通分量就是一个分组。

实现方案

下面提供两种可行的实现方式,分别基于并查集(高效轻量)和NetworkX图库(简洁直观)。

方式1:并查集算法(高效轻量)

并查集适合处理大规模数据的连通性问题,无需额外依赖第三方图库。

import pandas as pd

# 1. 创建示例DataFrame
data = {
    'Frame_number': ['Frame 1']*3 + ['Frame 2']*3 + ['Frame 3']*3 + ['Frame 4']*3 + ['Frame 5']*3 + ['Frame 6']*3,
    'Color_ID': [(10,5), (11,8), (12,9)]*3 + [(80,5), (11,8), (12,9)]*2 + [(80,6), (11,8), (12,9)]
}
df = pd.DataFrame(data)

# 2. 实现并查集类
class UnionFind:
    def __init__(self, elements):
        self.parent = {elem: elem for elem in elements}
    
    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):
        # 合并两个连通分量
        x_root = self.find(x)
        y_root = self.find(y)
        if x_root != y_root:
            self.parent[y_root] = x_root

# 3. 提取唯一Color_ID并初始化并查集
unique_color_ids = df['Color_ID'].unique()
uf = UnionFind(unique_color_ids)

# 4. 遍历元组对,合并有交集的元组
for i in range(len(unique_color_ids)):
    set_i = set(unique_color_ids[i])
    for j in range(i+1, len(unique_color_ids)):
        set_j = set(unique_color_ids[j])
        if set_i & set_j:  # 存在元素交集
            uf.union(unique_color_ids[i], unique_color_ids[j])

# 5. 生成组ID映射
group_mapping = {}
root_to_group = {}
current_group = 0
for elem in unique_color_ids:
    root = uf.find(elem)
    if root not in root_to_group:
        root_to_group[root] = current_group
        current_group += 1
    group_mapping[elem] = root_to_group[root]

# 6. 将组ID添加到原DataFrame
df['Group_ID'] = df['Color_ID'].map(group_mapping)

# 查看分组结果
print(df.groupby('Group_ID')['Color_ID'].unique())

方式2:NetworkX图库(简洁直观)

如果不需要考虑极致性能,用NetworkX的连通分量功能可以快速实现逻辑,代码更简洁。

import pandas as pd
import networkx as nx

# 1. 创建示例DataFrame(同方式1)
data = {
    'Frame_number': ['Frame 1']*3 + ['Frame 2']*3 + ['Frame 3']*3 + ['Frame 4']*3 + ['Frame 5']*3 + ['Frame 6']*3,
    'Color_ID': [(10,5), (11,8), (12,9)]*3 + [(80,5), (11,8), (12,9)]*2 + [(80,6), (11,8), (12,9)]
}
df = pd.DataFrame(data)

# 2. 提取唯一Color_ID并构建图
unique_color_ids = df['Color_ID'].unique()
G = nx.Graph()
G.add_nodes_from(unique_color_ids)

# 3. 为有交集的元组添加边
for i in range(len(unique_color_ids)):
    set_i = set(unique_color_ids[i])
    for j in range(i+1, len(unique_color_ids)):
        set_j = set(unique_color_ids[j])
        if set_i & set_j:
            G.add_edge(unique_color_ids[i], unique_color_ids[j])

# 4. 获取连通分量并生成组ID映射
connected_components = list(nx.connected_components(G))
group_mapping = {}
for idx, comp in enumerate(connected_components):
    for elem in comp:
        group_mapping[elem] = idx

# 5. 添加组ID到DataFrame
df['Group_ID'] = df['Color_ID'].map(group_mapping)

# 查看分组结果
print(df.groupby('Group_ID')['Color_ID'].unique())

结果验证

两种方式都会得到如下分组:

  • Group 0: [(10,5), (80,5), (80,6)]
  • Group 1: [(11,8)]
  • Group 2: [(12,9)]

完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:50:18