将数据框转换为网络图绘制所需的格式

3

I have a dataframe like so:

ID  | Node 1 | Node 2 | Node 3
a   |   1    |    0   |   1
b   |   0    |    1   |   1
c   |   1    |    0   |   0
d   |   1    |    1   |   1
e   |   0    |    1   |   1

我想将它改为网络图,其中节点之间的连接是它们共同出现次数的ID数量:
Node A | Node B | Weight |
Node 1 | Node 2 |    1   |
Node 1 | Node 3 |    2   |
Node 2 | Node 3 |    3   |

这只用于三列吗?还是您打算用它来处理更多列? - Alex
最好能够处理动态列数(最多60列)的更多内容。 - NBC
4个回答

5
基于 Tai 的解决方案(来源),您可以使用以下方式获取所需的 DataFrame:
import numpy as np
import pandas as pd

def get_weights(df):
    df2 = df.filter(regex='Node')
    nodes = df2.columns
    arr = df2.values
    m = np.dot(arr.T, arr).astype(float)
    idx = np.tril_indices(m.shape[0])   
    m[idx] = np.nan
    result = pd.DataFrame(m, columns=nodes, index=nodes)
    result = result.stack()
    result = result.astype(int)
    result = result.reset_index()
    result.columns = ['Node A', 'Node B', 'Weights']
    return result

df = pd.DataFrame({'ID': ['a', 'b', 'c', 'd', 'e'],
 'Node 1': [1, 0, 1, 0, 0],
 'Node 2': [0, 1, 0, 1, 1],
 'Node 3': [1, 1, 0, 1, 1]})
result = get_weights(df)
print(result)

产生

   Node A  Node B  Weight
0  Node 1  Node 2       1
1  Node 1  Node 3       2
2  Node 2  Node 3       3

1

不再采用边缘列表形式

Node A | Node B | Weight |
Node 1 | Node 2 |    1   |
Node 1 | Node 3 |    2   |
Node 2 | Node 3 |    3   |

你还可以计算共现/邻接矩阵来表示你感兴趣的关系。它可以使用点积构建。alko已经在pandas中给出了答案,详见用python pandas构建共现矩阵
我使用numpy修改了alko的答案。
m = df.values.T.dot(df.values)
np.fill_diagonal(m, 0)

# array([[0, 1, 2],
#       [1, 0, 3],
#       [2, 3, 0]])
# You can use nx.from_numpy_matrix to construct a graph
# m[i, j] is the number of co-occurance between node i and node j.

我不喜欢alko的答案中的一部分,即试图通过更改df.values来更改数据框的对角线部分。直接更改df.values以更改df不应该被提倡,因为有时df.values返回一个副本,有时返回一个视图。有关更多信息,请参见我的先前问题Will changes in DataFrame.values always modify the values in the data frame?
如果想要遵循alko的pandas方法,可以使用df = df - np.eye(len(df)) * np.diagonal(df)替换np.fill_diagonal(df.values, 0)

1

将数据框转换为邻接矩阵

您可以遍历数据框以创建一个numpy数组:

import pandas as pd
import numpy as np
from itertools import combinations
import networkx as nx

df = pd.DataFrame({'node_1': [1,0,1,1,0], 
                   'node_2':[0,1,0,1,1], 
                   'node_3':[1,1,0,1,1]})

# Array dimension
l = len(df.columns)
# empty matrice
mat = np.zeros((l,l))

for i, row in df.iterrows():
    positions = np.where(row)[0]
    if len(positions)>1:
        for comb in combinations(positions,2):
            i,j = comb
            mat[i,j] += 1
            mat[j,i] += 1

mat

array([[ 0., 1., 2.], [ 1., 0., 3.], [ 2., 3., 0.]])

从Numpy邻接矩阵创建Networkx图

G = nx.Graph(mat)
G.edges(data=True)

[out]: EdgeDataView([(0, 1, {'weight': 1.0}), (0, 2, {'weight': 2.0}), (1, 2, {'weight': 3.0})])

[out]: EdgeDataView([(0, 1, {'权重': 1.0}), (0, 2, {'权重': 2.0}), (1, 2, {'权重': 3.0})])


0
你可以先使用itertools找到所有的组合,然后找到每对的权重。
import itertools
(
     pd.DataFrame(list(itertools.combinations(df.set_index('ID').columns,2)), 
                  columns=['Node A', 'Node B'])
     .assign(Weight=lambda y: y.apply(lambda x: df[[x['Node A'],x['Node B']]]
                                                .all(1).sum(), axis=1))
)

Out[39]: 
   Node A  Node B  Weight
0  Node 1  Node 2       1
1  Node 1  Node 3       2
2  Node 2  Node 3       3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接