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

Pandas如何基于groupby与传递性规则实现交易地址聚类

这个场景不需要手动逐组遍历校验传递关系,本质是无向图连通分量检测问题,用图算法或者并查集可以直接实现,逻辑天然覆盖你提到的两条聚类规则。

核心逻辑

把每个地址视为无向图的节点,同一笔交易内的所有地址属于直接关联的节点,最终所有互相连通的节点自动构成一个地址簇,传递性会在连通关系计算时自动生效,不需要额外写判断逻辑。

可直接运行的实现方案

先构造示例测试数据:

import pandas as pd
from itertools import combinations
import networkx as nx

df = pd.DataFrame({
    'TX_ID': [1,2,2,1,2,3],
    'Address': ['address2','address3','address1','address1','address4','address50']
})

方案1:NetworkX图计算(代码最简洁,适合中小规模数据)

直接用图计算库的现成连通分量接口,代码量最少:

# 初始化无向图
G = nx.Graph()

# 按交易ID分组,为同交易地址建立关联
for _, addr_group in df.groupby('TX_ID')['Address']:
    addr_list = addr_group.unique()
    if len(addr_list) == 1:
        G.add_node(addr_list[0])
    else:
        # 同一交易下的地址两两建立连边
        G.add_edges_from(combinations(addr_list, 2))

# 提取连通分量,即最终地址簇
clusters = list(nx.connected_components(G))

运行得到的clusters和预期结果完全匹配:

[{'address1', 'address2', 'address3', 'address4'}, {'address50'}]

方案2:原生并查集实现(性能更高,适合百万级以上大数据量)

如果数据量很大,不想依赖图计算库,可以自己实现轻量的并查集(不相交集合)结构,内存占用和运行速度都更优:

class UnionFind:
    def __init__(self):
        self.parent = dict()

    def find_root(self, node):
        # 路径压缩优化
        if self.parent[node] != node:
            self.parent[node] = self.find_root(self.parent[node])
        return self.parent[node]

    def merge(self, a, b):
        # 初始化新节点
        if a not in self.parent:
            self.parent[a] = a
        if b not in self.parent:
            self.parent[b] = b
        root_a = self.find_root(a)
        root_b = self.find_root(b)
        if root_a != root_b:
            self.parent[root_b] = root_a

uf = UnionFind()
# 遍历每个交易的地址组,合并同组地址
for _, addr_group in df.groupby('TX_ID')['Address']:
    addr_list = addr_group.unique()
    first_addr = addr_list[0]
    for addr in addr_list[1:]:
        uf.merge(first_addr, addr)

# 按根节点聚合得到所有簇
cluster_dict = dict()
for addr in uf.parent:
    root = uf.find_root(addr)
    if root not in cluster_dict:
        cluster_dict[root] = []
    cluster_dict[root].append(addr)
clusters = list(cluster_dict.values())

结果格式化

如果需要输出示例里的标注格式,直接遍历打印即可:

for idx, cluster in enumerate(clusters, 1):
    print(f"CLUSTER{idx}: {sorted(cluster)}")

输出:

CLUSTER1: ['address1', 'address2', 'address3', 'address4']
CLUSTER2: ['address50']

两种方案都不需要手动编写多层循环校验跨交易的地址传递关系,只要把同交易的地址做关联,算法会自动把所有存在关联路径的地址归为同一个簇,哪怕地址跨越多笔交易也能正确识别。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 00:21:40