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

如何用Matplotlib绘制规范数字总线图?现有临时实现求优化

绘制数字总线图的标准原生实现方式

我想要绘制如图所示的数字总线图:
Bus diagram

自己写了一段临时实现代码,但想知道是否存在更标准的原生绘图方式。

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

# 示例数据
x = [0, 1, 4, 7]
y = ['000', '001', '111', '111']

# 定义高度和侧边顶角角度
height = 0.5
angle = 160  # 单位:度

# 简单三角函数计算
angle_rad = np.deg2rad(angle)
base = height / np.tan(angle_rad / 2)

# 绘图
fig, ax = plt.subplots(figsize=(15,1))  
for i in range(len(x)-1):
    polygon_width = x[i+1]-x[i]
    polygon = patches.Polygon([[x[i], 0], 
                               [x[i]+base/2, height], 
                               [x[i]+polygon_width-base/2, height], 
                               [x[i+1], 0], 
                               [x[i]+polygon_width-base/2, -height], 
                               [x[i]+base/2, -height]],
                               closed=True, facecolor='white', edgecolor='black')
    ax.add_patch(polygon)
    plt.text(x[i]+polygon_width/2, 0, y[i], ha='center', va='center')

plt.xlim([min(x), max(x)])
plt.ylim([-1.5, 1.5])  
plt.xlabel('时间')
plt.ylabel('总线位')
plt.title('总线随时间变化')
plt.yticks([])
plt.show()

我的代码运行结果如图:
plot


更标准的原生实现思路

Matplotlib没有专门的“总线图”原生绘图函数,但可以通过组合原生组件实现更简洁、易维护的方案:

方案1:结合broken_barh与单线条绘制

通过broken_barh绘制中间矩形块,再单独绘制两侧斜边,逻辑更拆分,便于调整样式:

import matplotlib.pyplot as plt
import numpy as np

x = [0, 1, 4, 7]
y = ['000', '001', '111', '111']
height = 0.5
angle = 160
angle_rad = np.deg2rad(angle)
base = height / np.tan(angle_rad / 2)

fig, ax = plt.subplots(figsize=(15,1))

for i in range(len(x)-1):
    start = x[i]
    width = x[i+1] - x[i]
    # 绘制中间矩形块
    ax.broken_barh([(start, width-base)], (-height, 2*height), facecolor='white', edgecolor='black')
    # 绘制左侧斜边
    ax.plot([start, start+base/2], [0, height], 'k-')
    ax.plot([start, start+base/2], [0, -height], 'k-')
    # 绘制右侧斜边
    ax.plot([start+width-base/2, start+width], [height, 0], 'k-')
    ax.plot([start+width-base/2, start+width], [-height, 0], 'k-')
    # 添加总线文本
    ax.text(start + width/2, 0, y[i], ha='center', va='center')

ax.set_xlim(min(x), max(x))
ax.set_ylim(-1.5, 1.5)
ax.set_xlabel('时间')
ax.set_ylabel('总线位')
ax.set_title('总线随时间变化')
ax.set_yticks([])
plt.show()

方案2:用LineCollection批量绘制斜边

如果数据量较大,使用LineCollection批量管理所有斜边,绘图效率更高:

import matplotlib.pyplot as plt
import matplotlib.collections as mcollections
import numpy as np

x = [0, 1, 4, 7]
y = ['000', '001', '111', '111']
height = 0.5
angle = 160
angle_rad = np.deg2rad(angle)
base = height / np.tan(angle_rad / 2)

fig, ax = plt.subplots(figsize=(15,1))

lines = []
for i in range(len(x)-1):
    start = x[i]
    width = x[i+1] - x[i]
    # 绘制中间矩形块
    ax.broken_barh([(start, width-base)], (-height, 2*height), facecolor='white', edgecolor='black')
    # 收集所有斜边线段
    lines.append([(start, 0), (start+base/2, height)])
    lines.append([(start, 0), (start+base/2, -height)])
    lines.append([(start+width-base/2, height), (start+width, 0)])
    lines.append([(start+width-base/2, -height), (start+width, 0)])
    # 添加总线文本
    ax.text(start + width/2, 0, y[i], ha='center', va='center')

# 批量添加斜边到画布
line_collection = mcollections.LineCollection(lines, colors='black')
ax.add_collection(line_collection)

ax.set_xlim(min(x), max(x))
ax.set_ylim(-1.5, 1.5)
ax.set_xlabel('时间')
ax.set_ylabel('总线位')
ax.set_title('总线随时间变化')
ax.set_yticks([])
plt.show()

以上两种方案均基于Matplotlib原生组件,相比直接绘制多边形,逻辑更模块化,样式调整也更灵活。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:47:02