绘制x和y的副轴时缺少一个辅助标签

6 投票
1 回答
2206 浏览
提问于 2025-04-17 21:09

我之前在这个问题上学习了如何在同一个图表上绘制两个 x 轴和两个 y 轴,链接在这里:Matplotlib: 两个 x 轴和两个 y 轴

这是一个简单的示例:

import matplotlib.pyplot as plt
import numpy as np

# Generate random data.    
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)

# Plot both curves.
fig = plt.figure()

ax1 = fig.add_subplot(111)
ax1.set_xlabel('x_1')
ax1.set_ylabel('y_1')
plt.plot(x1, y1, c='r')

ax2 = ax1.twinx().twiny()
ax2.set_xlabel('x_2')
ax2.set_ylabel('y_2')
plt.ylim(min(y2), max(y2))
ax2.plot(x2, y2, c='b')

plt.show()

这是输出结果:

在这里输入图片描述

右边的 y 轴和上面的 x 轴对应的是蓝色曲线。

如你所见,第二个 y 标签虽然已经定义了,但却没有显示出来。我尝试了很多不同的方法,但就是无法让它显示。难道我做错了什么吗?


补充:

显然,下面这行代码有问题:

ax2 = ax1.twinx().twiny()

如果我把它反过来写成这样:

ax2 = ax1.twiny().twinx()

那么第二个 x 标签就不会显示了。

1 个回答

4

基本上,发生的事情是你创建了一个第三个坐标轴对象,但你现在没有保存对它的引用。ax2的可见y轴实际上是属于这个第三个坐标轴对象的。

你有几个选择。

  1. 保留对这个“隐藏”坐标轴对象的引用,并设置它的y标签。
  2. 不使用twinxtwiny,而是直接在第一个坐标轴的位置创建一个新的坐标轴。

第二个选项稍微复杂一点,但好处是第二个图的y轴范围会自动调整,正如你所期望的那样。你不需要像现在这样手动设置它们。

无论如何,这里是第一个选项的一个例子:

import matplotlib.pyplot as plt
import numpy as np

# Generate random data.
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)

# Plot both curves.
fig, ax1 = plt.subplots()

ax1.set(xlabel='x_1', ylabel='y_1')
ax1.plot(x1, y1, c='r')

tempax = ax1.twinx()
ax2 = tempax.twiny()
ax2.plot(x2, y2, c='b')
ax2.set(xlabel='x_2', ylim=[min(y2), max(y2)])
tempax.set_ylabel('y_2', rotation=-90)

plt.show()

...这是第二个选项的一个例子:

import matplotlib.pyplot as plt
import numpy as np

def twinboth(ax):
    # Alternately, we could do `newax = ax._make_twin_axes(frameon=False)`
    newax = ax.figure.add_subplot(ax.get_subplotspec(), frameon=False)
    newax.xaxis.set(label_position='top')
    newax.yaxis.set(label_position='right', offset_position='right')
    newax.yaxis.get_label().set_rotation(-90) # Optional...
    newax.yaxis.tick_right()
    newax.xaxis.tick_top()
    return newax

# Generate random data.
x1 = np.random.randn(50)
y1 = np.linspace(0, 1, 50)
x2 = np.random.randn(20)+15.
y2 = np.linspace(10, 20, 20)

# Plot both curves.
fig, ax1 = plt.subplots()

ax1.set(xlabel='x_1', ylabel='y_1')
ax1.plot(x1, y1, c='r')

ax2 = twinboth(ax1)
ax2.set(xlabel='x_2', ylabel='y_2')
ax2.plot(x2, y2, c='b')

plt.show()

这两种方法的输出是完全相同的:

enter image description here

撰写回答