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

如何高效为Pandas DataFrame列基于相邻列共享值重标注,适配百万级数据

高效解决方案:基于并查集(DSU)实现

你原有逻辑本质是求r_id和c_id构成的二分图的连通分量,再将同一分量内的所有c_id映射到分量内最早出现的基准c_id。networkx作为通用图计算库额外开销极高,不适合百万级数据。使用带路径压缩+按秩合并的并查集实现,时间复杂度接近线性,250万行数据可在几秒内处理完成。

实现步骤

  • 预计算每个r_id首次出现对应的c_id,作为该r_id的基准值
  • 给所有r_id和c_id分配唯一整数ID,区分两个ID空间避免冲突
  • 遍历所有行,对每行的r_id和c_id执行合并操作
  • 为每个连通分量分配基准c_id,优先取分量内所有r_id对应的首次c_id的最小值
  • 将原c_id映射到对应分量的基准值,得到最终结果

完整代码实现

import pandas as pd

# 并查集核心实现,带路径压缩和按秩合并
class DSU:
    def __init__(self, size):
        self.parent = list(range(size))
        self.rank = [0]*size
    
    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:
            return
        # 按秩合并
        if self.rank[x_root] < self.rank[y_root]:
            self.parent[x_root] = y_root
        else:
            self.parent[y_root] = x_root
            if self.rank[x_root] == self.rank[y_root]:
                self.rank[x_root] += 1

# ---------------------- 处理流程 ----------------------
# 1. 加载数据,兼容任意类型的r_id和c_id
r1 = ['x', 'y', 'z', 'u', 'v', 'w', 'x']
r2 = ['1', '1', '2', '3', '3', '4', '4']
df = pd.DataFrame([r1,r2]).T
df.columns = ['r_id', 'c_id']

# 2. 预计算每个r_id首次出现的c_id
r_first_c = df.drop_duplicates('r_id', keep='first').set_index('r_id')['c_id'].to_dict()

# 3. 给r_id、c_id分配唯一整数ID,避免ID冲突
unique_cid = df['c_id'].unique()
cid_to_id = {c:i for i, c in enumerate(unique_cid)}
unique_rid = df['r_id'].unique()
rid_to_id = {r:i+len(unique_cid) for i, r in enumerate(unique_rid)}
total_nodes = len(unique_cid) + len(unique_rid)

# 4. 初始化DSU并执行合并操作
dsu = DSU(total_nodes)
for rid, cid in zip(df['r_id'], df['c_id']):
    dsu.union(rid_to_id[rid], cid_to_id[cid])

# 5. 构建根节点到基准c_id的映射
root_to_target = {}
# 优先用r_id的首次c_id作为基准值
for rid in unique_rid:
    root = dsu.find(rid_to_id[rid])
    if root not in root_to_target or r_first_c[rid] < root_to_target[root]:
        root_to_target[root] = r_first_c[rid]
# 补充无关联r_id的c_id的映射
for cid in unique_cid:
    root = dsu.find(cid_to_id[cid])
    if root not in root_to_target:
        root_to_target[root] = cid

# 6. 生成最终结果
df['simplified'] = df['c_id'].apply(lambda x: root_to_target[dsu.find(cid_to_id[x])])

性能优化提示

  • 数据量极大时可将遍历逻辑替换为numpy向量化操作,可再提速30%以上
  • 无需存储完整图结构,内存开销仅为O(唯一节点数),250万行数据内存占用可控制在100MB以内
  • 若r_id、c_id本身为连续整数,可省略ID映射步骤直接调整偏移量,进一步降低开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:36:02