【问题标题】:Construct NetworkX graph from Pandas DataFrame从 Pandas DataFrame 构建 NetworkX 图
【发布时间】:2014-02-08 01:55:55
【问题描述】:

我想从一个简单的 Pandas DataFrame 创建一些 NetworkX 图:

        Loc 1   Loc 2   Loc 3   Loc 4   Loc 5   Loc 6   Loc 7
Foo     0       0       1       1       0       0           0
Bar     0       0       1       1       0       1           1
Baz     0       0       1       0       0       0           0
Bat     0       0       1       0       0       1           0
Quux    1       0       0       0       0       0           0

其中Foo… 是索引,Loc 1Loc 7 是列。但是转换为 Numpy 矩阵或重新数组似乎不适用于为nx.Graph() 生成输入。是否有实现此目标的标准策略?我不反对在 Pandas 中重新格式化数据 --> 转储到 CSV --> 导入到 NetworkX,但似乎我应该能够从索引中生成边,从值中生成节点。

【问题讨论】:

    标签: python pandas networkx


    【解决方案1】:

    NetworkX expects a square matrix(节点和边),也许*你想通过它:

    In [11]: df2 = pd.concat([df, df.T]).fillna(0)
    

    注意:索引和列的顺序很重要!

    In [12]: df2 = df2.reindex(df2.columns)
    
    In [13]: df2
    Out[13]: 
           Bar  Bat  Baz  Foo  Loc 1  Loc 2  Loc 3  Loc 4  Loc 5  Loc 6  Loc 7  Quux
    Bar      0    0    0    0      0      0      1      1      0      1      1     0
    Bat      0    0    0    0      0      0      1      0      0      1      0     0
    Baz      0    0    0    0      0      0      1      0      0      0      0     0
    Foo      0    0    0    0      0      0      1      1      0      0      0     0
    Loc 1    0    0    0    0      0      0      0      0      0      0      0     1
    Loc 2    0    0    0    0      0      0      0      0      0      0      0     0
    Loc 3    1    1    1    1      0      0      0      0      0      0      0     0
    Loc 4    1    0    0    1      0      0      0      0      0      0      0     0
    Loc 5    0    0    0    0      0      0      0      0      0      0      0     0
    Loc 6    1    1    0    0      0      0      0      0      0      0      0     0
    Loc 7    1    0    0    0      0      0      0      0      0      0      0     0
    Quux     0    0    0    0      1      0      0      0      0      0      0     0
    
    In[14]: graph = nx.from_numpy_matrix(df2.values)
    

    这不会将列/索引名称传递给图表,如果您想这样做,您可以使用relabel_nodes(您可能必须警惕重复,这在 pandas 的 DataFrames 中是允许的):

    In [15]: graph = nx.relabel_nodes(graph, dict(enumerate(df2.columns))) # is there nicer  way than dict . enumerate ?
    

    *对于所需图表,列和索引到底代表什么尚不清楚。

    【讨论】:

    • 索引代表例如一个人,列表示给定人所属的组。
    【解决方案2】:

    答案有点晚,但是now networkx can read data from pandas dataframes,在这种情况下,理想情况下,简单有向图的格式如下:

    +----------+---------+---------+
    |   Source |  Target |  Weight |
    +==========+=========+=========+
    | Node_1   | Node_2  |   0.2   |
    +----------+---------+---------+
    | Node_2   | Node_1  |   0.6   |   
    +----------+---------+---------+
    

    如果您使用的是邻接矩阵,那么 Andy Hayden 是对的,您应该注意正确的格式。由于在您的问题中您使用了 0 和 1,我想您希望看到一个无向图。自从您说 Index 代表例如一个人,列代表给定人所属的组,但另一方面,组(成员资格)属于一个人也是正确的。按照这个逻辑,您实际上应该将组放在索引中,并将人员也放在列中。

    附注:您也可以在有向图的意义上定义此问题,例如,您希望可视化分层类别的关联网络。在那里,协会例如从 Samwise Gamgee 到 Hobbits 通常比在另一个方向上更强(因为 Frodo Baggins 更可能是 Hobbit 原型)

    【讨论】:

      【解决方案3】:

      你也可以像这样使用 scipy 创建方阵:

      import scipy.sparse as sp
      
      cols = df.columns
      X = sp.csr_matrix(df.astype(int).values)
      Xc = X.T * X  # multiply sparse matrix
      Xc.setdiag(0)  # reset diagonal
      
      # create dataframe from co-occurence matrix in dense format
      df = pd.DataFrame(Xc.todense(), index=cols, columns=cols)
      

      稍后您可以从数据框创建边缘列表并将其导入 Networkx:

      df = df.stack().reset_index()
      df.columns = ['source', 'target', 'weight']
      
      df = df[df['weight'] != 0]  # remove non-connected nodes
      
      g = nx.from_pandas_edgelist(df, 'source', 'target', ['weight'])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-26
        • 2021-08-17
        • 1970-01-01
        • 2014-08-09
        • 2019-04-22
        • 2019-07-08
        • 2023-02-09
        • 2023-04-08
        相关资源
        最近更新 更多