如何用Dash实现点击气泡图气泡生成对应分类的NetworkX网络图
完整Dash实现方案
前置依赖安装
执行以下命令安装需要的依赖库:
pip install dash plotly networkx pandas
完整可运行代码
import dash from dash import dcc, html, Input, Output, callback import plotly.graph_objects as go import networkx as nx import pandas as pd # ---------------------- 数据预处理 ---------------------- # 原始数据表 df = pd.DataFrame([ ["cat1", "node1", "target1"], ["cat1", "node2", "target1"], ["cat1", "node2", "target2"], ["cat1", "node2", "target3"], ["cat1", "node2", "target4"], ["cat2", "node3", "target1"], ["cat2", "node3", "target1"], ["cat2", "node4", "target7"], ["cat2", "node6", "target7"], ], columns=["category", "source_node", "target_node"]) # 按分类预存边列表 category_edges = df.groupby("category").apply( lambda x: x[["source_node", "target_node"]].to_dict("records") ).to_dict() # 分类坐标、条目数配置 node_plot_location_dict = {'cat1': [10, 4], 'cat2': [3, 4]} category_count = df["category"].value_counts().to_dict() # ---------------------- Dash页面配置 ---------------------- app = dash.Dash(__name__) app.layout = html.Div([ dcc.Location(id='url', refresh=True), html.H3("分类气泡图"), dcc.Graph(id="bubble-chart"), html.Hr(), html.H3("分类关系网络图"), dcc.Graph(id="network-graph"), ]) # ---------------------- 回调逻辑 ---------------------- # 初始化气泡图 @callback( Output("bubble-chart", "figure"), Input("bubble-chart", "id") ) def update_bubble(_): categories = list(node_plot_location_dict.keys()) fig = go.Figure(data=[go.Scatter( x = [node_plot_location_dict[c][0] for c in categories], y = [node_plot_location_dict[c][1] for c in categories], mode = 'markers+text', text = categories, textposition = 'top center', marker = dict( size = [category_count[c] * 10 for c in categories], # 气泡大小关联分类条目数 opacity = 0.7 ), customdata = categories # 存储分类名用于点击时识别 )]) fig.update_layout(clickmode='event+select', showlegend=False) return fig # 点击气泡更新网络图 @callback( Output("network-graph", "figure"), Input("bubble-chart", "clickData"), prevent_initial_call=False ) def update_network(click_data): # 未点击时显示提示 if not click_data: return go.Figure().add_annotation( text="点击上方气泡图的分类查看对应网络图", showarrow=False, font={"size": 20} ) # 获取选中分类 selected_cat = click_data["points"][0]["customdata"] edges = category_edges[selected_cat] # 生成NetworkX图 G = nx.Graph() for edge in edges: G.add_edge(edge["source_node"], edge["target_node"]) # 计算节点布局坐标,固定seed保证布局稳定 pos = nx.spring_layout(G, seed=42) # 绘制边 edge_traces = [] for edge in G.edges(): x0, y0 = pos[edge[0]] x1, y1 = pos[edge[1]] edge_traces.append(go.Scatter( x = [x0, x1, None], y = [y0, y1, None], line = dict(width=1, color="#888"), mode = "lines", hoverinfo = "none" )) # 绘制节点 node_x, node_y, node_text, node_links = [], [], [], [] for node in G.nodes(): x, y = pos[node] node_x.append(x) node_y.append(y) node_text.append(node) # 自定义节点跳转链接规则,可按需修改 node_links.append(f"https://example.com/node/{node}") node_trace = go.Scatter( x = node_x, y = node_y, mode = "markers+text", text = node_text, textposition = "top center", marker = dict(size=20, line_width=2), customdata = node_links, hoverinfo = "text" ) # 组装网络图 fig = go.Figure(data=edge_traces + [node_trace]) fig.update_layout( showlegend=False, clickmode="event+select", xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), yaxis=dict(showgrid=False, zeroline=False, showticklabels=False) ) return fig # 点击网络图节点跳转对应页面 @callback( Output("url", "href"), Input("network-graph", "clickData"), prevent_initial_call=True ) def node_redirect(click_data): return click_data["points"][0]["customdata"] if __name__ == "__main__": app.run_server(debug=True)
效果说明
- 运行代码后访问默认的
http://127.0.0.1:8050即可使用交互功能 - 气泡大小与分类下的条目数量正相关,点击任意分类气泡,下方会自动渲染该分类的关系网络图
- 点击网络图的任意节点,会自动跳转到提前配置的对应链接
Jupyter环境可选方案
如果需要在Jupyter中直接使用,可替换为ipywidgets+plotly的组合实现相同效果,核心的联动逻辑与上述代码一致,无需启动独立的Dash服务。
内容的提问来源于stack exchange,提问作者Slowat_Kela
相关产品推荐
相关产品推荐

