如何用Matplotlib绘制规范数字总线图?现有临时实现求优化
绘制数字总线图的标准原生实现方式
我想要绘制如图所示的数字总线图:
自己写了一段临时实现代码,但想知道是否存在更标准的原生绘图方式。
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()
我的代码运行结果如图:
更标准的原生实现思路
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
相关产品推荐
相关产品推荐

