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

如何在Matplotlib、Plotly和NetworkX中绘制重复X轴范围的网络图

使用Plotly实现带重复X轴域的NetworkX网络图

核心思路

要实现重复X轴域(每个域对应0-100范围)的网络图,关键在于:

  • 为每个节点计算基于域编号的偏移X坐标,确保不同域的节点落在独立的0-100区间内
  • 自定义X轴刻度,将累计的偏移坐标映射为每个域的0-100显示文本
  • 用Plotly的散点图和线条分别绘制节点与边

完整代码示例

假设你已有包含节点域编号、域内相对位置的DataFrame,以下是可直接运行的实现代码:

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

# ---------------------- 示例数据(替换为你的实际数据) ----------------------
nodes_df = pd.DataFrame({
    'node_id': [1, 2, 3, 4, 5, 6],
    'domain': [12, 12, 13, 13, 14, 14],
    'x_in_domain': [20, 70, 30, 80, 50, 90],  # 域内0-100的相对位置
    'y': [50, 30, 60, 20, 40, 70],            # Y轴坐标
    'node_color': [10, 20, 30, 40, 50, 60]    # 节点颜色属性(可选)
})

edges_df = pd.DataFrame({
    'source': [1, 2, 3, 5],
    'target': [3, 4, 5, 6]
})
# -------------------------------------------------------------------------

# 创建NetworkX图
G = nx.Graph()
G.add_nodes_from(nodes_df['node_id'])
G.add_edges_from(edges_df[['source', 'target']].values)

# 计算节点实际X坐标:域偏移量 + 域内相对位置
min_domain = nodes_df['domain'].min()
nodes_df['x'] = (nodes_df['domain'] - min_domain) * 100 + nodes_df['x_in_domain']

# 准备边的坐标数据
edge_x, edge_y = [], []
for src, tgt in G.edges():
    src_x = nodes_df.loc[nodes_df['node_id'] == src, 'x'].values[0]
    src_y = nodes_df.loc[nodes_df['node_id'] == src, 'y'].values[0]
    tgt_x = nodes_df.loc[nodes_df['node_id'] == tgt, 'x'].values[0]
    tgt_y = nodes_df.loc[nodes_df['node_id'] == tgt, 'y'].values[0]
    
    edge_x.extend([src_x, tgt_x, None])  # None用于分隔不同边
    edge_y.extend([src_y, tgt_y, None])

# 准备节点的坐标与 hover 文本
node_x = nodes_df['x'].tolist()
node_y = nodes_df['y'].tolist()
node_text = [
    f"节点ID: {n}<br>域编号: {d}<br>域内X: {x}" 
    for n, d, x in zip(nodes_df['node_id'], nodes_df['domain'], nodes_df['x_in_domain'])
]

# 构建Plotly图
fig = go.Figure()

# 添加边轨迹
fig.add_trace(go.Scatter(
    x=edge_x, y=edge_y,
    mode='lines',
    line=dict(width=0.8, color='#666'),
    hoverinfo='none'
))

# 添加节点轨迹
fig.add_trace(go.Scatter(
    x=node_x, y=node_y,
    mode='markers',
    marker=dict(
        size=12,
        color=nodes_df['node_color'],
        colorscale='Viridis',
        colorbar=dict(title='节点属性'),
        line=dict(width=1, color='#fff')
    ),
    text=node_text,
    hoverinfo='text'
))

# 自定义X轴:每个域显示0-100刻度
unique_domains = sorted(nodes_df['domain'].unique())
tick_vals = []
tick_text = []

for idx, _ in enumerate(unique_domains):
    domain_start = idx * 100
    # 添加0、50、100三个刻度点
    tick_vals.extend([domain_start, domain_start+50, domain_start+100])
    tick_text.extend(['0', '50', '100'])

# 设置布局
fig.update_layout(
    xaxis=dict(
        tickvals=tick_vals,
        ticktext=tick_text,
        title='域(0-100)',
        showgrid=True,
        gridcolor='#eee',
        range=[-10, len(unique_domains)*100 + 10]  # 预留左右边距
    ),
    yaxis=dict(
        title='Y坐标',
        showgrid=True,
        gridcolor='#eee'
    ),
    showlegend=False,
    hovermode='closest',
    height=600,
    width=1200
)

# 添加域分隔虚线
for idx in range(1, len(unique_domains)):
    fig.add_vline(x=idx*100, line_width=2, line_dash='dash', line_color='#aaa')

fig.show()

关键细节说明

  1. 坐标计算:通过(域编号 - 最小域编号)*100为每个域创建独立的100单位宽度区间,叠加域内相对位置得到节点最终X坐标。
  2. X轴自定义:利用tickvals和ticktext将累计坐标映射为每个域的0-100显示文本,配合垂直虚线清晰分隔不同域。
  3. 边的绘制:用None分隔每条边的线段,确保Plotly正确渲染独立的边。

你可以根据实际需求调整节点大小、颜色、边样式等参数,完全匹配你的参考图效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:15:50