plotly-network-graph.py
plotly-network-graph
import%20marimo%0A%0A__generated_with%20%3D%20%220.12.6%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%23%20Network%20Graphs%20in%20Plotly%20with%20Edge%20label%20on%20hover%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%20%20%20%20import%20networkx%20as%20nx%0A%0A%20%20%20%20G%20%3D%20nx.random_geometric_graph(200%2C%200.125)%0A%20%20%20%20return%20G%2C%20go%2C%20nx%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22It's%20trivial%20to%20create%20a%20%5Bnetwork%20graph%5D(https%3A%2F%2Fplotly.com%2Fpython%2Fnetwork-graphs%2F)%20in%20Plotly%20and%20it%20looks%20great.%20You%20can%20configure%20to%20show%20the%20node%20labels%20on%20hover%2C%20however%20there%20is%20no%20easy%20to%20show%20labels%20on%20edges%20on%20hover.%20After%20a%20lot%20of%20googling%20I%20found%20this%20%5BStackoverflow%20post%5D(https%3A%2F%2Fstackoverflow.com%2Fquestions%2F74607000%2Fpython-networkx-plotly-how-to-display-edges-mouse-over-text%2F74633879%2374633879)%20which%20hacks%20it%20by%20creating%20bunch%20of%20transparent%20points%20along%20the%20edge%20which%20can%20show%20label%20on%20hover.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(G%2C%20go)%3A%0A%20%20%20%20edge_x%20%3D%20%5B%5D%0A%20%20%20%20edge_y%20%3D%20%5B%5D%0A%20%20%20%20for%20edge%20in%20G.edges()%3A%0A%20%20%20%20%20%20%20%20x0%2C%20y0%20%3D%20G.nodes%5Bedge%5B0%5D%5D%5B'pos'%5D%0A%20%20%20%20%20%20%20%20x1%2C%20y1%20%3D%20G.nodes%5Bedge%5B1%5D%5D%5B'pos'%5D%0A%20%20%20%20%20%20%20%20edge_x.append(x0)%0A%20%20%20%20%20%20%20%20edge_x.append(x1)%0A%20%20%20%20%20%20%20%20edge_x.append(None)%0A%20%20%20%20%20%20%20%20edge_y.append(y0)%0A%20%20%20%20%20%20%20%20edge_y.append(y1)%0A%20%20%20%20%20%20%20%20edge_y.append(None)%0A%0A%20%20%20%20edge_trace%20%3D%20go.Scatter(%0A%20%20%20%20%20%20%20%20x%3Dedge_x%2C%20y%3Dedge_y%2C%0A%20%20%20%20%20%20%20%20line%3Ddict(width%3D0.5%2C%20color%3D'%23888')%2C%0A%20%20%20%20%20%20%20%20hoverinfo%3D'none'%2C%0A%20%20%20%20%20%20%20%20mode%3D'lines')%0A%0A%20%20%20%20node_x%20%3D%20%5B%5D%0A%20%20%20%20node_y%20%3D%20%5B%5D%0A%20%20%20%20for%20node%20in%20G.nodes()%3A%0A%20%20%20%20%20%20%20%20x%2C%20y%20%3D%20G.nodes%5Bnode%5D%5B'pos'%5D%0A%20%20%20%20%20%20%20%20node_x.append(x)%0A%20%20%20%20%20%20%20%20node_y.append(y)%0A%0A%20%20%20%20node_trace%20%3D%20go.Scatter(%0A%20%20%20%20%20%20%20%20x%3Dnode_x%2C%20y%3Dnode_y%2C%0A%20%20%20%20%20%20%20%20mode%3D'markers'%2C%0A%20%20%20%20%20%20%20%20hoverinfo%3D'text'%2C%0A%20%20%20%20%20%20%20%20marker%3Ddict(%0A%20%20%20%20%20%20%20%20%20%20%20%20showscale%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20colorscale%20options%0A%20%20%20%20%20%20%20%20%20%20%20%20%23'Greys'%20%7C%20'YlGnBu'%20%7C%20'Greens'%20%7C%20'YlOrRd'%20%7C%20'Bluered'%20%7C%20'RdBu'%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%23'Reds'%20%7C%20'Blues'%20%7C%20'Picnic'%20%7C%20'Rainbow'%20%7C%20'Portland'%20%7C%20'Jet'%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%23'Hot'%20%7C%20'Blackbody'%20%7C%20'Earth'%20%7C%20'Electric'%20%7C%20'Viridis'%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D'YlGnBu'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20reversescale%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3D%5B%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20size%3D10%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorbar%3Ddict(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20thickness%3D15%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3Ddict(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text%3D'Node%20Connections'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20side%3D'right'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20xanchor%3D'left'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line_width%3D2))%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20edge%2C%0A%20%20%20%20%20%20%20%20edge_trace%2C%0A%20%20%20%20%20%20%20%20edge_x%2C%0A%20%20%20%20%20%20%20%20edge_y%2C%0A%20%20%20%20%20%20%20%20node%2C%0A%20%20%20%20%20%20%20%20node_trace%2C%0A%20%20%20%20%20%20%20%20node_x%2C%0A%20%20%20%20%20%20%20%20node_y%2C%0A%20%20%20%20%20%20%20%20x%2C%0A%20%20%20%20%20%20%20%20x0%2C%0A%20%20%20%20%20%20%20%20x1%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20y0%2C%0A%20%20%20%20%20%20%20%20y1%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(G%2C%20node_trace)%3A%0A%20%20%20%20node_adjacencies%20%3D%20%5B%5D%0A%20%20%20%20node_text%20%3D%20%5B%5D%0A%20%20%20%20for%20_%2C%20adjacencies%20in%20enumerate(G.adjacency())%3A%0A%20%20%20%20%20%20%20%20node_adjacencies.append(len(adjacencies%5B1%5D))%0A%20%20%20%20%20%20%20%20node_text.append(str(len(adjacencies%5B1%5D)))%0A%0A%20%20%20%20node_trace.marker.color%20%3D%20node_adjacencies%0A%20%20%20%20node_trace.text%20%3D%20node_text%0A%20%20%20%20return%20adjacencies%2C%20node_adjacencies%2C%20node_text%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(G%2C%20go)%3A%0A%20%20%20%20def%20_()%3A%0A%20%20%20%20%20%20%20%20mnode_x%2C%20mnode_y%2C%20mnode_txt%20%3D%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%0A%20%20%20%20%20%20%20%20edge_x%2C%20edge_y%20%3D%20%5B%5D%2C%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20idx0%2C%20idx1%20in%20G.edges()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20x0%2C%20y0%20%3D%20G.nodes%5Bidx0%5D%5B%22pos%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20x1%2C%20y1%20%3D%20G.nodes%5Bidx1%5D%5B%22pos%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20edge_x.extend(%5Bx0%2C%20x1%2C%20None%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20edge_y.extend(%5By0%2C%20y1%2C%20None%5D)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20mnode_x.extend(%5B(x0%20%2B%20x1)%2F2%5D)%20%23%20assuming%20values%20positive%2Fget%20midpoint%0A%20%20%20%20%20%20%20%20%20%20%20%20mnode_y.extend(%5B(y0%20%2B%20y1)%2F2%5D)%20%23%20assumes%20positive%20vals%2Fget%20midpoint%0A%20%20%20%20%20%20%20%20%20%20%20%20mnode_txt.extend(%5Bf%22%23%20%7Bround(x0%2C%201)%7D%22%5D)%20%23%20hovertext%0A%0A%20%20%20%20%20%20%20%20return%20go.Scatter(x%20%3D%20mnode_x%2C%20y%20%3D%20mnode_y%2C%20mode%20%3D%20%22markers%22%2C%20showlegend%20%3D%20False%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%20%3D%20%22Edge%20%25%7Bhovertext%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hovertext%20%3D%20mnode_txt%2C%20marker%20%3D%20go.scatter.Marker(opacity%20%3D%200))%0A%0A%0A%20%20%20%20mnode_trace%20%3D%20_()%0A%20%20%20%20return%20(mnode_trace%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(edge_trace%2C%20go%2C%20mnode_trace%2C%20node_trace)%3A%0A%20%20%20%20fig%20%3D%20go.Figure(data%3D%5Bedge_trace%2C%20node_trace%2C%20mnode_trace%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20layout%3Dgo.Layout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3Ddict(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text%3D%22%3Cbr%3ENetwork%20graph%20made%20with%20Python%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20font%3Ddict(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D16%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hovermode%3D'closest'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20margin%3Ddict(b%3D20%2Cl%3D5%2Cr%3D5%2Ct%3D40)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20annotations%3D%5B%20dict(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text%3D%22Python%20code%3A%20%3Ca%20href%3D'https%3A%2F%2Fplotly.com%2Fpython%2Fnetwork-graphs%2F'%3E%20https%3A%2F%2Fplotly.com%2Fpython%2Fnetwork-graphs%2F%3C%2Fa%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20showarrow%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20xref%3D%22paper%22%2C%20yref%3D%22paper%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3D0.005%2C%20y%3D-0.002%20)%20%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20xaxis%3Ddict(showgrid%3DFalse%2C%20zeroline%3DFalse%2C%20showticklabels%3DFalse)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20yaxis%3Ddict(showgrid%3DFalse%2C%20zeroline%3DFalse%2C%20showticklabels%3DFalse))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20fig.show()%0A%20%20%20%20return%20(fig%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
82b19640ff0138aee8b77b9a93d54c092a37809a6c01aebcdf7f9b84f6d84ed4