将非方形邻接矩阵导入 Networkx python

Importing non-square adjacency matrix into Networkx python

我在下面的 pandas 数据框表单中有一些数据,其中列代表离散的技能,行代表离散的工作。仅当工作需要技能时才出现 1,否则出现 0。

     skill_1, skill_2,
job_1      1,       0,       
job_2      0,       0,       
job_3      1,       1,       

我想创建一个图表来可视化工作和技能之间的这种关系,使用 networkx。我尝试了两种方法,一种是在数据帧上,它本身是 nx.from_pandas_adjacencynx.from_numpy_matrix。后一种方法应用于数据框的 numpy 表示,其中删除了列名和行名。

在任何一种情况下,都会出现错误,因为这是一个 non_square 矩阵。这是有道理的,因为 networkx 可能将列和行解释为同一组节点。但是,列和节点在这里代表截然不同的事物。两个工作通过他们共享的技能联系起来,两个技能通过他们共享的工作联系起来,但是任何两个技能或任何两个工作之间没有直接的优势。

鉴于我的行和列是不同的节点集,我如何将我的数据导入 networkx?

一个选项是生成缺失的行和列

(我对实现此目的的矢量化方法感到好奇,所以我询问了 ,其中提供了提供此类方法的答案。)

df = pd.DataFrame({'skill_1': {'job_1': 1, 'job_2': 0, 'job_3': 1},
 'skill_2': {'job_1': 0, 'job_2': 0, 'job_3': 1}})

edges = df.columns

for i in df.index:
    df[i] = [0 for _ in range(len(df.index))]

for e in edges:
    df = df.append(pd.Series({c:0 for c in df.columns},name=e))

这给了我们:

>>> df
         skill_1  skill_2  job_1  job_2  job_3
job_1          1        0      0      0      0
job_2          0        0      0      0      0
job_3          1        1      0      0      0
skill_1        0        0      0      0      0
skill_2        0        0      0      0      0

然后我们可以使用 nx.from_pandas_adjacency 读入 networkx(假设您想要一个有向图)

G = nx.from_pandas_adjacency(df, create_using=nx.DiGraph)

或者,我们可以使用 df.stack()

df = pd.DataFrame({'skill_1': {'job_1': 1, 'job_2': 0, 'job_3': 1},
 'skill_2': {'job_1': 0, 'job_2': 0, 'job_3': 1}})

G = nx.DiGraph()

for x,y in df.stack().reset_index().iterrows():
    G.add_node(y['level_0'])
    G.add_node(y['level_1'])
    if y[0]:
        G.add_edge(y['level_0'], y['level_1'])

你有一个bipartite graph. Networkx can create this network from your original (bi)adjacency matrix using nx.algorithms.bipartite.matrix.from_biadjacency_matrix

正如 ComplexGates 所提到的,这里有一个双邻接矩阵。我看到您添加了一个解决方案,您在其中用零填充矩阵的其余部分以使其成为正方形。但是,我怀疑您真正想要的是如何将双邻接矩阵转换为(方形)邻接矩阵,这与发布的解决方案不同。

对于 m 行 n 列的双邻接矩阵 A,您可以将其转换为大小为 (m+n)x(m+n) 的邻接矩阵,如下所示:

┏           ┓
┃0_nxn A^T  ┃
┃A_mxn 0_mxm┃
┗           ┛

也就是说,把A放在(m+n)x(m+n)矩阵的左下角,把A的转置放在右上角,剩下的space用零。

在代码中,如果 A 是一个 2D Numpy 数组,您可以这样做:

def bipartite_to_adjacency(A):
     m, n = A.shape
     Z_mm = np.zeros((m,m), dtype=int)
     Z_nn = np.zeros((n,n), dtype=int)
     top_partition = np.concatenate((Z_nn,np.transpose(A)), axis=1)
     bottom_partition = np.concatenate((A,Z_mm), axis=1)
     return np.concatenate((top_partition, bottom_partition))