大型无环父子关系DataFrame遍历函数的性能优化问询
大型DataFrame父子关系匹配优化需求
匹配规则
- 每个子项至少拥有一个父项;
- 多个子项可共享同一父项;
- 最终父项需来自指定列表,链中共享该父项的所有子项将分配其ID用于后续操作;
- 若最终父项不在指定列表中,则回溯至前序父项,直至找到列表中的父项。
初始DataFrame示例
| Name | ChildPosition | ParentPosition |
|---|---|---|
| AAA | 39602320 | 10092002 |
| BBB | 10092002 | 50002102 |
| CCC | 10131807 | 10109077 |
| DDD | 10062441 | 39602320 |
| EEE | 39602320 | 39600136 |
| FFF | 39600136 | 10092002 |
指定列表示例
| Name | Position | ID |
|---|---|---|
| VVV | 50002102 | 689 |
| TTT | 10092002 | 731 |
如示例所示,AAA与BBB应共享父项VVV,均分配ID 689。
当前递归遍历实现
def walk(df, id, f, r, prev=pd.Series(dtype="int64")): """ Recursively traverse a DataFrame to retrieve a chain of values based on specified conditions. Parameters: df (pd.DataFrame): The DataFrame to traverse. id: The starting identifier for the traversal. f (str): The column name used to filter rows in the DataFrame. r (str): The column name whose values are collected during traversal. prev (pd.Series, optional): A series used to accumulate values during recursion. Returns: pd.Series: A series containing values collected during traversal. """ mgr = df.loc[df[f] == id,][r] if not mgr.isna().all(): prev = walk(df, mgr.tolist()[0], f, r, prev) return pd.concat([mgr, prev])
使用方式
df = df.assign( mgrs=lambda x: x["ChildPosition"].apply( lambda e: ( walk(x, e, "ChildPosition", "ParentCode") .dropna() .astype("int64") .tolist() ) ), emps=lambda x: x["ChildPosition"].apply( lambda e: ( walk(x, e, "ParentCode", "ChildPosition") .dropna() .astype("int64") .tolist() ) ), )
性能问题
当前方法执行耗时过长,单次调用需83秒,多次调用理论耗时达数小时,现寻求可行的优化方案以缩短执行时间。
预期输出示例(来自真实DataFrame)
| Children | Parents |
|---|---|
| 39602320 | [39600136, 39600136, 10092002, 10092002, 10102028, 39604655, 50008982, 10074224, 10074224, 50002171, 10134484, 50002102, 50002102] |
| 10131807 | [10109077, 10109077, 10070230, 10070230, 10073971, 10073971, 10133209, 10133209, 68505160, 68505160, 10074224, 10074224, 50002171, 10134484, 50002102, 50002102] |
| 10062441 | [39602320, 39602320, 39600136, 39600136, 10092002, 10092002, 10102028, 39604655, 50008982, 10074224, 10074224, 50002171, 10134484, 50002102, 50002102] |
| 10052497 | [10109077, 10109077, 10070230, 10070230, 10073971, 10073971, 10133209, 10133209, 68505160, 68505160, 10074224, 10074224, 50002171, 10134484, 50002102, 50002102] |
| 10112867 | [10130906, 10130906, 68017568, 68017568, 68502208, 68502208, 10091176, 10091176, 10135119, 10135119, 68505303, 68505303, 10134484, 10134484, 50002171, 50002171, 50002102, 50002102] |
注:上述提取覆盖整个DataFrame,部分Position未在初始示例中出现是因位于DataFrame后续行;重复条目代表月度数据,需保留。后续可提取Parents列反转后与指定列表匹配。
内容的提问来源于stack exchange,提问作者NoobQuestions1
相关产品推荐
相关产品推荐

