如何在Matplotlib次坐标轴上调整曲线排列顺序?
Matplotlib曲线显示层级调整方案
需求说明
需要调整曲线的显示顺序:让参数为0.01的蓝色曲线显示在最上层,参数0.1的橙色曲线次之,以此类推,参数越大的曲线越靠下,最终达到目标效果的层级。
当前代码
import matplotlib.pyplot as plt import numpy as np def calc_curve(x, y): n = x / y z = np.abs(n * x - y) * (1 - (x / y) * np.exp(-x / y)) + \ np.abs(x - y) * (x / y) * np.exp(-x / y) return z x_val = np.linspace(0.004, 0.4, 100) # plot fig, ax1 = plt.subplots() ax2 = ax1.twinx() z_val = np.zeros_like(x_val) for ts in [0.01, 0.1, 0.2, 0.3]: for c, tr in enumerate(x_val): z_val[c] = calc_curve(ts, x_val[c]) ax1.plot(x_val, z_val, label="parameter: {0}".format(ts)) ax1.set_xlim(np.min(x_val), np.max(x_val)) ax1.legend() plt.grid(True, which='both') plt.show()
效果对比
- 当前效果(曲线层级与需求相反):

- 目标效果(小参数曲线在上层):

解决方案
Matplotlib默认后绘制的曲线会覆盖先绘制的曲线,当前代码先画小参数曲线、后画大参数曲线,导致小参数曲线被覆盖。以下两种方法可解决问题:
方法1:反转参数遍历顺序
把参数列表倒序遍历,先绘制大参数曲线,再绘制小参数曲线,让小参数曲线自然覆盖在大参数曲线之上:
import matplotlib.pyplot as plt import numpy as np def calc_curve(x, y): n = x / y z = np.abs(n * x - y) * (1 - (x / y) * np.exp(-x / y)) + \ np.abs(x - y) * (x / y) * np.exp(-x / y) return z x_val = np.linspace(0.004, 0.4, 100) fig, ax1 = plt.subplots() ax2 = ax1.twinx() z_val = np.zeros_like(x_val) # 反转参数顺序,先画大参数,后画小参数 for ts in [0.3, 0.2, 0.1, 0.01]: for c, tr in enumerate(x_val): z_val[c] = calc_curve(ts, x_val[c]) ax1.plot(x_val, z_val, label="parameter: {0}".format(ts)) ax1.set_xlim(np.min(x_val), np.max(x_val)) ax1.legend() plt.grid(True, which='both') plt.show()
方法2:手动设置zorder参数
zorder控制曲线的显示层级,值越大的曲线显示越靠上。给小参数曲线设置更大的zorder值,无需修改遍历顺序:
import matplotlib.pyplot as plt import numpy as np def calc_curve(x, y): n = x / y z = np.abs(n * x - y) * (1 - (x / y) * np.exp(-x / y)) + \ np.abs(x - y) * (x / y) * np.exp(-x / y) return z x_val = np.linspace(0.004, 0.4, 100) fig, ax1 = plt.subplots() ax2 = ax1.twinx() z_val = np.zeros_like(x_val) # 为每个参数指定对应的zorder,参数越小zorder越大 param_zorder_map = {0.01:4, 0.1:3, 0.2:2, 0.3:1} for ts in [0.01, 0.1, 0.2, 0.3]: for c, tr in enumerate(x_val): z_val[c] = calc_curve(ts, x_val[c]) ax1.plot(x_val, z_val, label="parameter: {0}".format(ts), zorder=param_zorder_map[ts]) ax1.set_xlim(np.min(x_val), np.max(x_val)) ax1.legend() plt.grid(True, which='both') plt.show()
内容的提问来源于stack exchange,提问作者medicus3453
相关产品推荐
相关产品推荐

