Reputation: 97
I am creating a networkx graph and while developing in Python I can change the node size using the following code in networkx.draw_shell() -
vertices = df_final.columns.values.tolist()
edges = [((u,v),df_final[u].corr(df_final[v])) for u,v in itertools.combinations(vertices, 2)]
edges = [(u,v,{'weight': abs(c)}) for (u,v),c in edges if abs(c) >= 0.5]
G = networkx.Graph()
G.add_edges_from(edges)
size = F_imp.Score.to_list()
from matplotlib.pyplot import figure
figure(figsize=(9,9), dpi=500)
networkx.draw_shell(G, with_labels=True, node_size= (np.array(size) *10000), font_size=8)
plt.show()
But when I am trying to integrate the same plot in Dash, I can't use the networkx.draw_shell() in built function anymore and hence can't use the node_size attribute anymore. Rather I have to transform the network graph into a plotly graph in the following way -
vertices = df_final.columns.values.tolist()
edges = [((u,v),df_final[u].corr(df_final[v])) for u,v in itertools.combinations(vertices, 2)]
#edges = [(u,v,{'weight': c}) for (u,v),c in edges if abs(c) >= 0.5]
edges = [(u,v,{'weight': abs(c)}) for (u,v),c in edges if abs(c) >= 0.5]
G = networkx.Graph()
G.add_edges_from(edges)
#size = F_imp.Score.to_list()
pos = networkx.shell_layout(G)
networkx.shell_layout
import plotly.graph_objects as go
# edges trace
edge_x = []
edge_y = []
for edge in G.edges():
x0, y0 = pos[edge[0]]
x1, y1 = pos[edge[1]]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(color='black', width=1),
hoverinfo='none',
showlegend=False,
mode='lines')
# nodes trace
node_x = []
node_y = []
text = []
for node in G.nodes():
x, y = pos[node]
node_x.append(x)
node_y.append(y)
text.append(node)
node_trace = go.Scatter(
x=node_x, y=node_y, text=text,
mode='markers+text',
showlegend=False,
hoverinfo='none',
marker=dict(
color='pink',
size=50,
line=dict(color='black', width=1)))
# size nodes by degree
# deg_dict = {deg[0]:int(deg[1]) for deg in list(G.degree())}
# for node, degree in enumerate(deg_dict):
# node_trace['marker']['size'] = (deg_dict[degree])
# layout
layout = dict(plot_bgcolor='white',
paper_bgcolor='white',
margin=dict(t=10, b=10, l=10, r=10, pad=0),
xaxis=dict(linecolor='black',
showgrid=False,
showticklabels=False,
mirror=True),
yaxis=dict(linecolor='black',
showgrid=False,
showticklabels=False,
mirror=True))
# figure
fig = go.Figure(data=[edge_trace, node_trace], layout=layout)
fig
This does generate the network graph but I am not being able to assign different node sizes to the nodes based on some score as I could in the first case.
The size component in the node_trace['marker']['size'] seems to be applicable for all nodes and cannot be changed for each node. Here I tried to change the node size as per degree. The code has been commented out above under #size nodes by degree
As reference, I have followed the following questions -
Does anyone know the solution?
Upvotes: 1
Views: 1028
Reputation: 337
You can define a dictionary containing the node sizes and pass it list to the node_trace
variable.
I do not have your dataset, so I made just a small example.
Let's say this is your dictionary containing the sizes:
node_size = {
'Brown bear': 4,
'fur': 3,
'claw': 3,
'sharp': 2,
'brown': 2
}
While looping over your nodes, you create a list that contains the sizes of the corresponding nodes:
# nodes trace
node_x = []
node_y = []
text = []
sizes = []
for node in G.nodes():
x, y = pos[node]
node_x.append(x)
node_y.append(y)
text.append(node)
# Append the sizes
size = node_size[node]
sizes.append(size)
You pass this list as a parameter to the go.Scatter()
:
node_trace = go.Scatter(
x=node_x, y=node_y, text=text,
mode='markers+text',
showlegend=False,
# Add the sizes,
size=node_sizes,
hoverinfo='none',
marker=dict(
color='pink',
size=50,
line=dict(color='black', width=1)))
Run the rest of your code, and your plot has not variable node sizes. See my output screenshot as example:
Upvotes: 1