Python实现百万级ID根节点对账算法的高效方案问询
高效实现DataFrame中节点到根节点的映射(百万级数据适用)
对于百万行级的父子节点映射表,要快速找到每个节点的最顶层根节点,**并查集(Union-Find)**是最优选择——它的路径压缩和按秩合并优化能让操作时间复杂度接近O(n),完全适配大规模数据。
实现步骤
- 初始化并查集:把所有出现过的ID(父节点+子节点)都纳入,每个节点初始父节点设为自己(根节点的父节点就是自己)。
- 合并连通分量:遍历每一行父子对,将子节点合并到父节点的连通分量中;如果父节点为空(该子节点是根节点),则跳过合并。
- 路径压缩查询:对每个节点执行
find操作,直接返回其最顶层根节点,同时压缩路径加速后续查询。 - 映射回原DataFrame:将每个节点的根节点结果合并到原数据中。
完整代码实现
import pandas as pd def find_root(node, parent_dict): # 查找根节点,带路径压缩 if parent_dict[node] != node: parent_dict[node] = find_root(parent_dict[node], parent_dict) return parent_dict[node] def map_to_root(df, parent_col='Parent ID', child_col='Child ID'): # 收集所有出现过的ID all_ids = pd.concat([df[parent_col].dropna(), df[child_col]]).unique() # 初始化并查集字典 parent_dict = {id_: id_ for id_ in all_ids} # 用itertuples替代iterrows,提升百万级数据遍历效率 for row in df.itertuples(index=False): parent = getattr(row, parent_col) child = getattr(row, child_col) if pd.notna(parent): # 找到父节点和子节点的根 root_parent = find_root(parent, parent_dict) root_child = find_root(child, parent_dict) if root_parent != root_child: parent_dict[root_child] = root_parent # 为原DataFrame的每个子节点获取根节点 df['Root ID'] = df[child_col].apply(lambda x: find_root(x, parent_dict)) # 可选:给父节点也加上根节点映射 df['Parent Root ID'] = df[parent_col].apply(lambda x: find_root(x, parent_dict) if pd.notna(x) else x) return df # 测试示例 if __name__ == "__main__": data = { 'Parent ID': [1, 3, 3, 2, None], 'Child ID': [3, 4, 5, 6, 7] } df = pd.DataFrame(data) result_df = map_to_root(df) print("处理后结果:") print(result_df)
测试输出
处理后结果: Parent ID Child ID Root ID Parent Root ID 0 1.0 3 1 1.0 1 3.0 4 1 1.0 2 3.0 5 1 1.0 3 2.0 6 2 2.0 4 NaN 7 7 NaN
性能说明
- 用
itertuples()替代iterrows()能大幅提升百万级数据的遍历速度,避免pandas行对象的额外开销。 - 并查集的路径压缩确保后续查询几乎是O(1),百万级数据处理时间通常在几秒内完成,远优于递归或循环向上查找的方式(后者会重复遍历路径,时间复杂度可能达到O(n²))。
内容的提问来源于stack exchange,提问作者pythonlover
相关产品推荐
相关产品推荐

