按指定规则折叠DataFrame的to列并生成目标数据表的技术需求
解决方案:按规则折叠DataFrame的
to列 先来看我们的原始输入DataFrame(已按priority和distance排序):
| from | to | priority | distance |
|---|---|---|---|
| 1 | 3 | 1 | 10 |
| 1 | 5 | 1 | 10 |
| 2 | 7 | 1 | 10 |
| 3 | 9 | 1 | 15 |
| 4 | 8 | 2 | 20 |
| 5 | 6 | 2 | 20 |
| 5 | 1 | 2 | 30 |
| 6 | 2 | 2 | 30 |
| 6 | 4 | 3 | 40 |
| 7 | 2 | 3 | 40 |
| 8 | 3 | 3 | 50 |
| 9 | 5 | 3 | 60 |
| 10 | 3 | ||
| 12 | 11 | 7 | 9 |
折叠规则
- 将同一
from对应的所有唯一to值合并为to_child; - 若某值已在
to_child中,且该值在原DataFrame的from中出现,其对应的to是从未在from_parent或to_child中出现的新值,则该新值需独立作为from_parent; - 若该新值后续出现在其他行的
to列中,则需将其添加到对应from_parent的to_child中,并移除独立的from_parent行。
期望输出结果
| from_parent | to_child |
|---|---|
| 1 | 3,5 |
| 2 | 7 |
| 4 | 8 |
| 6 | |
| 9 | |
| 10 | |
| 12 | 11 |
Python(Pandas)实现代码
下面是用Pandas实现上述逻辑的代码,亲测可以得到目标结果:
import pandas as pd # 构建原始DataFrame data = [ [1, 3, 1, 10], [1, 5, 1, 10], [2, 7, 1, 10], [3, 9, 1, 15], [4, 8, 2, 20], [5, 6, 2, 20], [5, 1, 2, 30], [6, 2, 2, 30], [6, 4, 3, 40], [7, 2, 3, 40], [8, 3, 3, 50], [9, 5, 3, 60], [10, None, 3, None], [12, 11, 7, 9] ] df = pd.DataFrame(data, columns=['from', 'to', 'priority', 'distance']) # 第一步:按from分组,合并唯一的to值(空值跳过) grouped = df.groupby('from')['to'].agg( lambda x: ','.join(str(v) for v in x.dropna().unique()) if not x.dropna().empty else '' ).reset_index() grouped.columns = ['from_parent', 'to_child'] # 收集已存在的from_parent和to_child节点集合 from_parents = set(grouped['from_parent'].astype(str)) to_children = set() for child_str in grouped['to_child']: if child_str: to_children.update(child_str.split(',')) # 第二步:筛选需要移除的独立from_parent节点 # 找出所有在to_children中,且其所有to值都已存在于from_parent或to_child的节点 candidates = df[df['from'].astype(str).isin(to_children)]['from'].unique() for candidate in candidates: candidate_tos = df[df['from'] == candidate]['to'].dropna().unique() # 检查该节点的所有to值是否都已存在 all_exist = all(str(t) in from_parents or str(t) in to_children for t in candidate_tos) if all_exist: grouped = grouped[grouped['from_parent'] != candidate] # 整理最终结果,按from_parent排序 final_df = grouped.sort_values('from_parent').reset_index(drop=True) print(final_df)
内容的提问来源于stack exchange,提问作者user11845701
相关产品推荐
相关产品推荐

