Create NetowrkX Graph from Pandas DataFrame

Viewed 51

Im trying to create a graph from this data structure, where U are the nodes and C are the relations between the nodes U. Right now I have the following structure

df = pd.DataFrame({'C': ['C1', 'C2', 'C3', 'C4'], 'U1': [1,0,1,0], 'U2': [1,0,0,0], 'U3': [0,1,1,0], 'U4': [1,0,0,0], 'U5': [0,1,0,1]})

    C  U1  U2  U3  U4  U5
0  C1   1   1   0   1   0
1  C2   0   0   1   0   1
2  C3   1   0   1   0   0
3  C4   0   0   0   0   1

And I'm trying to accomplish the following mirror matrix:

       U1  U2  U3  U4  U5
0  U1   0   1   1   1   0
1  U2   1   0   0   1   0
2  U3   1   0   0   0   1
3  U4   1   1   0   0   0
3  U5   0   0   1   0   0

Is there a more efficient way to accomplish this than iterating through the rows of the original matrix? With this last resulting matrix the idea is to get the pairs of node that are connected.

For example (U1,U2) (U1,U3) (U1,U4) would be the connections of the first node.

2 Answers

IIUC, try:

df = pd.DataFrame({'C': ['C1', 'C2', 'C3', 'C4'], 'U1': [1,0,1,0], 'U2': [1,0,0,0], 'U3': [0,1,1,0], 'U4': [1,0,0,0], 'U5': [0,1,0,1]})
dfi =  df.set_index('C')
dfa = dfi.T.dot(dfi)
np.fill_diagonal(dfa.values, 0)
G=nx.from_pandas_adjacency(dfa)
fig, ax = plt.subplots()
nx.draw_networkx(G, ax=ax)

Output:

enter image description here

You can get that matrix by stacking into a Series and keeping only cells that are 1. Then merge with itself within connection and then crosstab the nodes.

df1 = df.set_index('C').stack().rename_axis(['C', 'U']).loc[lambda x: x==1].reset_index()[['C', 'U']]
df1 = df1.merge(df1, on='C').query('U_x != U_y')

df1 = pd.crosstab(df1['U_x'], df1['U_y']).clip(upper=1).rename_axis(index=None, columns=None)

    U1  U2  U3  U4  U5
U1   0   1   1   1   0
U2   1   0   0   1   0
U3   1   0   0   0   1
U4   1   1   0   0   0
U5   0   0   1   0   0
Related