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

2024-05-20 00:05:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我在下面的dataframe表单中有一些数据,其中列表示离散的技能,行表示离散的工作。仅当作业需要技能时,才显示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表示,其中删除了列名和行名

在这两种情况下,都会出现错误,因为这是一个非方矩阵。这是有意义的,因为networkx可能将列和行解释为同一组节点。然而,这里的列和节点代表着截然不同的东西。两项工作通过它们共享的技能连接,两项技能通过它们共享的工作连接,但任何两项技能或任何两项工作之间都没有直接的优势

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


Tags: 数据方法fromnumpynetworkx表单dataframe节点
3条回答

你有一个bipartite graph。Networkx可以使用nx.algorithms.bipartite.matrix.from_biadjacency_matrix从原始(bi)邻接矩阵创建此网络

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

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

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

换句话说,把A放在(m+n)x(m+n)矩阵的左下角,把A的转置放在右上角,用零填充剩余的空间

在代码中,如果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))

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

(我对实现这一点的矢量化方法很好奇,所以我问this question哪一个答案提供了这种方法。)

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'])

相关问题 更多 >