You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Plotly实现NetworkX节点与时间序列子图的联动交互

Got it, let's get this interactive linking working between your NetworkX graph and time series plot in Plotly. I’ve put together a practical, modifiable solution that fits your existing two-column subgraph setup:

Core Approach

We’ll use Plotly’s custom click event callbacks to connect the right-side NetworkX nodes to the left-side time series. Here’s the breakdown:

  1. Attach unique node IDs to each graph node using Plotly’s customdata attribute—this lets us identify exactly which node was clicked.
  2. Name each time series trace after its corresponding node ID, so we can match clicks to the correct curve.
  3. Write a JavaScript callback that listens for node clicks, then toggles visibility of time series traces to only show the clicked node’s data.
Full Code Example

Replace your existing subgraph code with this (swap out the sample data for your actual time series and NetworkX graph):

import plotly.graph_objects as go
import networkx as nx
import pandas as pd

# ---------------------- Replace with your actual data ----------------------
# Time series data: key = node ID, value = {x: timestamps, y: values}
ts_data = {
    "NodeA": {"x": pd.date_range(start="2023-01-01", periods=10), "y": [1,3,2,5,4,6,8,7,9,10]},
    "NodeB": {"x": pd.date_range(start="2023-01-01", periods=10), "y": [2,4,1,3,5,7,6,8,10,9]},
    "NodeC": {"x": pd.date_range(start="2023-01-01", periods=10), "y": [5,3,6,2,7,4,8,1,9,0]}
}

# Your existing NetworkX graph
G = nx.Graph()
G.add_nodes_from(["NodeA", "NodeB", "NodeC"])
G.add_edges_from([("NodeA", "NodeB"), ("NodeB", "NodeC")])
# ---------------------------------------------------------------------------

# Build the two-column figure
fig = go.Figure()

# 1. Left subplot: Time series traces
for node_id, data in ts_data.items():
    fig.add_trace(go.Scatter(
        x=data["x"], y=data["y"],
        name=node_id,  # Critical: Match this to node IDs in your graph
        visible=True,
        xaxis="x1", yaxis="y1"
    ))

# 2. Right subplot: NetworkX graph converted to Plotly
pos = nx.spring_layout(G)  # Use your preferred layout here
# Add nodes with customdata for ID tracking
node_x = [pos[node][0] for node in G.nodes()]
node_y = [pos[node][1] for node in G.nodes()]
fig.add_trace(go.Scatter(
    x=node_x, y=node_y,
    mode="markers+text",
    text=[node for node in G.nodes()],
    textposition="top center",
    marker=dict(size=15, color="#1f77b4"),
    customdata=[node for node in G.nodes()],  # Stores node ID for click events
    name="Nodes",  # Used to identify node traces in the callback
    xaxis="x2", yaxis="y2"
))
# Add edges
for edge in G.edges():
    x0, y0 = pos[edge[0]]
    x1, y1 = pos[edge[1]]
    fig.add_trace(go.Scatter(
        x=[x0, x1], y=[y0, y1],
        mode="lines",
        line=dict(width=2, color="#999999"),
        showlegend=False,
        xaxis="x2", yaxis="y2"
    ))

# Configure layout
fig.update_layout(
    grid=dict(rows=1, columns=2, width_ratios=[2, 1]),
    xaxis1=dict(domain=[0, 0.65], title="Time"),
    yaxis1=dict(title="Value"),
    xaxis2=dict(domain=[0.7, 1], showticklabels=False),
    yaxis2=dict(showticklabels=False),
    title="Interactive Time Series + Network Graph",
    height=600
)

# Add click event callback to link nodes to time series
fig.add_js_callback("""
// Track selected node (use an array here if you want multi-select)
let selectedNode = null;

// Listen for plot click events
document.addEventListener('plotly_click', function(event) {
    const clickedTrace = event.points[0].trace;
    // Only react to clicks on the node trace
    if (clickedTrace.name === 'Nodes') {
        const nodeId = event.points[0].customdata;
        selectedNode = nodeId;
        
        // Get all time series traces (adjust the filter if your traces are ordered differently)
        const tsTraces = document.getElementById('graph').data.filter(trace => trace.xaxis === 'x1');
        
        // Create visibility array: only show the clicked node's time series
        const visibility = tsTraces.map(trace => trace.name === nodeId ? true : false);
        
        // Update the time series subplot
        Plotly.restyle('graph', 'visible', visibility);
    }
});
""")

# Show the figure
fig.show(config={'displayModeBar': False})
Key Details to Adapt to Your Setup
  • Trace Matching: Make sure the name of each time series trace exactly matches the node ID in your NetworkX graph—this is how we link clicks to curves.
  • Trace Filtering: In the callback, tsTraces = document.getElementById('graph').data.filter(trace => trace.xaxis === 'x1') filters for left-subplot traces. If your trace ordering is different, adjust this filter to target only your time series traces.
  • Multi-Select: To let users click multiple nodes to show multiple curves, replace selectedNode with an array. Modify the callback to toggle node IDs in the array, then set visibility based on whether the trace name is in the selected array.
  • Graph ID: The code uses 'graph' as the Plotly figure's ID (default for inline plots). If you’re embedding the plot in a web page with a custom ID, update document.getElementById('graph') to match.

内容的提问来源于stack exchange,提问作者Natasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:22:45