使用Pandas构建含中转目的地的Origin-Destination矩阵
构建包含中转目的地的Origin-Destination矩阵
需求说明
需要构建包含中转目的地的Origin-Destination矩阵,将多级关联的路径信息整合到同一行中:把某个origin_id通过直接或间接关联得到的所有link_type对应的最终applied_id,都映射回该origin_id的对应列。
现有数据集
| origin_id | link_type | applied_id |
|---|---|---|
| 1 | A | 2 |
| 2 | B | 3 |
| 2 | D | 3 |
| 3 | C | 4 |
| 5 | D | 6 |
| 1 | E | 4 |
预期结果
| origin_id | A | B | C | D | E |
|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 3 | 4 |
| 2 | 3 | 4 | 3 | ||
| 3 | 4 | ||||
| 5 | 6 |
细节说明:例如origin_id=1通过link_type=A关联到2,2又通过B、D关联到3,3再通过C关联到4,这些路径对应的link_type和applied_id都要填充到origin_id=1的对应列;同时origin_id=1直接通过E关联到4,该信息也需保留。且不存在同一origin_id通过不同路径得到同一种link_type对应多个applied_id的冲突场景。
现有尝试问题
使用pivot_table仅能保留直接关联的信息,无法处理中转路径:
df.pivot_table(values='applied_id', index="origin_id", columns='link_type', aggfunc=max)
得到的结果不符合预期:
| origin_id | A | B | C | D |
|---|---|---|---|---|
| 1 | 2 | |||
| 2 | 3 | 3 | ||
| 3 | 4 |
解决方案
利用NetworkX构建有向图来处理多级关联路径,实现代码如下:
import pandas as pd import networkx as nx # 初始化数据集 df = pd.DataFrame({ 'origin_id': ['1', '2', '2', '3', '5', '1'], 'link_type': ['A', 'B', 'D', 'C', 'D', 'E'], 'applied_id':['2', '3', '3', '4', '6', '4'] }) # 从数据集构建带属性的有向图 G = nx.from_pandas_edgelist( df, source='origin_id', target='applied_id', edge_attr='link_type', create_using=nx.MultiDiGraph ) dict_for_df = {} # 指定需要提取的link_type列表 link_type_list = ['A', 'B', 'C', 'D', 'E'] for n in df['origin_id'].unique(): value_dict = {} for link_type in link_type_list: # 获取当前节点及其所有后代节点组成的子图 subgraph_nodes = {str(n)} | nx.descendants(G, str(n)) subgraph = G.subgraph(subgraph_nodes) # 筛选出当前link_type对应的目标节点(applied_id) target_ids = list(set( edge[1] for edge, attr in nx.get_edge_attributes(subgraph, 'link_type').items() if attr == link_type )) value_dict[link_type] = target_ids[0] if target_ids else None dict_for_df[n] = value_dict # 转换为DataFrame并调整格式 final = pd.DataFrame.from_dict(dict_for_df, orient='index').reset_index().rename(columns={'index':'origin_id'}) print(final)
代码逻辑说明
- 构建有向图:将每个交易ID作为节点,
origin_id到applied_id的关联作为有向边,边携带link_type属性; - 遍历处理每个origin_id:对每个
origin_id,获取其所有后代节点(即通过多级关联能到达的所有交易ID),组成子图; - 提取对应link_type的目标ID:在子图中筛选出每种
link_type对应的目标节点,利用题目中无冲突的特性,直接取唯一值; - 转换为矩阵格式:将字典转换为DataFrame,得到包含中转路径信息的Origin-Destination矩阵。
内容的提问来源于stack exchange,提问作者E. Faslo
相关产品推荐
相关产品推荐

