获取不同节点组的 NetworkX 二维位置作为附加 Pandas DataFrame 列

Get NetworkX 2D position of different group of nodes as an additional Pandas DataFrame column

我有一个 DataFrame 构造为边缘列表和多个子节点和边缘元数据列,大约有 10 000 个条目。

 Child    |    Parent    |   ChildCategory  |  ChildDescription |  EdgeType | Root |
  C1           'root'             X              Lorem Ipsum        Strong     C1
  C2             C1               X              Lorem Ipsum        Strong     C1
  C3             C2               Y              Lorem Ipsum        Strong     C1
  C4             C2               Y              Lorem Ipsum        Strong     C1
  C5           'root'             X              Lorem Ipsum        Strong     C5
  C6             C5               X              Lorem Ipsum        Strong     C5
  C7             C6               Y              Lorem Ipsum         Weak      C5
  ...           ...              ...                 ...              ..       .. 

我可以使用 networkx 将数据帧转换为图形。

  G = nx.from_pandas_edgelist(df,source="Parent",target= "Child",edge_attr=["EdgeType"],create_using = nx.MultiDiGraph())
  node_meta_data = ["ChildCategory","ChildDescription","Root"]
  for col in node_meta_data:
      nx.set_node_attributes(G,dict(zip(node_list_df,df[col].fillna('').tolist())),col)

我现在想做的是获取每组 Root 列的每个节点的二维位置,并将其返回到 DataFrame 列,以便我可以在另一个程序中可视化节点。

如果我要在整个图上做,我可以这样做。

df = pd.DataFrame(index=G.nodes())
for col in node_meta_data:
     df[col] = pd.Series(nx.get_node_attributes(G, col))
df['EdgeType'] = nx.get_edge_attributes(G,'EdgeType')


### Here is the problem. 
df['position'] = pd.Series(nx.kamada_kawai_layout(G))) ##Without group by root.

#### But I need position per group of root.
....

但是我将如何针对每个根组执行此操作,是否可以以智能方式将 pandas group_byG.subgraph() 一起使用?

编辑:位置列应反映子列的位置。

您似乎想要从每个 root 节点开始的不同子图。为此,您需要更改每个 root 节点的名称,因为必须区分它们。一种方式可能是:

is_root = df.Parent.eq("'root'")
df.loc[is_root, 'Parent'] += is_root.cumsum().astype(str)

这将给出:

print(node_list_df)

  Child   Parent ChildCategory ChildDescription EdgeType Root
0    C1  'root'1             X       LoremIpsum   Strong   C1
1    C2       C1             X       LoremIpsum   Strong   C1
2    C3       C2             Y       LoremIpsum   Strong   C1
3    C4       C2             Y       LoremIpsum   Strong   C1
4    C5  'root'2             X       LoremIpsum   Strong   C5
5    C6       C5             X       LoremIpsum   Strong   C5
6    C7       C6             Y       LoremIpsum     Weak   C5

现在,如果我们从修改后的数据框构建图,我们现在会得到两个不同的子图,对于来自每个 root 节点的后继者:

G = nx.from_pandas_edgelist(node_list_df,source="Parent",
                          target= "Child",
                          create_using = nx.DiGraph())

pos = nx.kamada_kawai_layout(G)

nx.draw(G, pos=pos, 
        node_color='lightblue', 
        with_labels=True,
        node_size=500)

我们现在可以使用布局中的位置更新数据框:

pos = (pd.DataFrame(pos, index=['x', 'y']).T
         .rename_axis('Parent')
         .reset_index())
df_out = node_list_df.merge(pos, on='Parent', sort=False)

print(df_out)

  Child   Parent ChildCategory ChildDescription EdgeType Root         x  \
0    C1  'root'1             X       LoremIpsum   Strong   C1  1.000000   
1    C2       C1             X       LoremIpsum   Strong   C1  0.467196   
2    C3       C2             Y       LoremIpsum   Strong   C1 -0.055515   
3    C4       C2             Y       LoremIpsum   Strong   C1 -0.055515   
4    C5  'root'2             X       LoremIpsum   Strong   C5 -0.883338   
5    C6       C5             X       LoremIpsum   Strong   C5 -0.345431   
6    C7       C6             Y       LoremIpsum     Weak   C5  0.200324   

          y  
0 -0.002704  
1  0.149699  
2  0.333853  
3  0.333853  
4 -0.230175  
5 -0.363323  
6 -0.459552