如何添加具有非均匀间隔和不同比例的辅助 matplotlib 轴

How to add secondary matplotlib axis with non-uniform interval and different scale

我有三个数组:timestepsvolume。我想绘制 volume(Y 轴)如何随 time(X 轴)变化并演示 time 如何与 steps(第二个 X 轴)相关联.

time = np.array([1.280000e-07, 1.322240e-07, 1.364480e-07, 1.288448e-06,
       1.288448e-06, 1.288448e-06, 1.292672e-06, 1.292672e-06,
       1.420672e-06, 1.424896e-06, 1.429120e-06, 2.581120e-06,
       2.581120e-06, 2.581120e-06, 2.585344e-06, 2.585344e-06,
       2.586400e-06, 2.587456e-06, 2.603456e-06])

steps = np.arange(1,20)

volume = np.array([256., 384., 512., 512., 384., 256., 128.,   0., 256., 384., 512.,
   512., 384., 256., 128.,   0.,  32.,  64.,  96.])

来自 time 的时间值链接到相应的 steps 值,例如 step[1] 发生在 time[1]step[2] 发生在 time[2]

我试过 twiny() 但它似乎只有在两个轴之间的比例相同时才有效。在下面的图中,两个轴在值之间具有统一的间隔并且均匀分布。

fig, ax1 = plt.subplots(1, 1, figsize=(10, 4.5), dpi=160, facecolor='w', edgecolor='k', sharey=True)
ax1.plot(t,volume)
ax2 = ax1.twiny()
ax2.set_xticks(steps)

如何根据 time 轴缩放 steps 轴?

A twin ax 是一个新的 ax 放置在与原始位置相同的位置,但将其刻度设置在另一侧。默认情况下,原始刻度和新刻度之间没有关系,但可以通过仔细设置轴限制来暗示这种关系。

相反,secondary ax 设置刻度之间的固定关系。如果没有显式设置关系,它将是身份关系。

为了得到你想要的结果,你可以设置这样一个副轴,把steps作为标签,用time定位。

看起来像:

import numpy as np
import matplotlib.pyplot as plt

time = np.array([1.28e-07, 1.32224e-07, 1.36448e-07, 1.288448e-06, 1.288448e-06, 1.288448e-06, 1.292672e-06, 1.292672e-06, 1.420672e-06, 1.424896e-06, 1.42912e-06, 2.58112e-06, 2.58112e-06, 2.58112e-06, 2.585344e-06, 2.585344e-06, 2.5864e-06, 2.587456e-06, 2.603456e-06])
steps = np.arange(1, 20)
volume = np.array([256., 384., 512., 512., 384., 256., 128., 0., 256., 384., 512., 512., 384., 256., 128., 0., 32., 64., 96.])

fig, ax1 = plt.subplots(1, 1, figsize=(10, 4.5),  facecolor='w', edgecolor='k')
ax1.plot(time, volume)
secax = ax1.secondary_xaxis('top')
secax.set_xticks(time)
secax.set_xticklabels(steps)
plt.show()

由于许多时间位置相同或靠得很近,因此生成的标签重叠。一个解决方案可能是将这些重叠的标签放在一起并创建一个标签范围:

pos = []
labels = []
start_step = steps[0]
for prev_t, t, prev_step, step in zip(time,
                                      np.append(time[1:], np.inf),
                                      steps,
                                      np.append(steps[1:], 0)):
    if (t - prev_t) > prev_t / 20:
        pos += [prev_t]
        if start_step == prev_step:
            labels += [f'{start_step}']
        else:
            labels += [f'{start_step}-{prev_step}']
        start_step = step
secax.set_xticks(pos)
secax.set_xticklabels(labels)