Matplotlib twiny:如何在一个绘图中对齐两个xax的值?

2024-06-11 22:50:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用matplotlib中的twiny()从由以下数据块组成的XML文件中绘制一条带有两个x轴的曲线:

<data>
<meas>
  <utc>2018-11-10T22:27:06.500003</utc>
  <ra_j2000>23.9722686269</ra_j2000>
  <dec_j2000>-1.23845121893</dec_j2000>
  <mag>9.96074403533</mag>
</meas>

<meas>
  <utc>2018-11-10T22:27:54.500002</utc>
  <ra_j2000>23.9930913364</ra_j2000>
  <dec_j2000>-1.03788334773</dec_j2000>
  <mag>11.356437889</mag>
</meas>

<meas>
  <utc>2018-11-10T22:38:36.500002</utc>
  <ra_j2000>0.267638646848</ra_j2000>
  <dec_j2000>1.56055091433</dec_j2000>
  <mag>11.1642458641</mag>
</meas>

<meas>
  <utc>2018-11-10T22:46:18.500000</utc>
  <ra_j2000>0.462353662364</ra_j2000>
  <dec_j2000>3.34334963425</dec_j2000>
  <mag>11.1082534741</mag>
</meas>

<meas>
  <utc>2018-11-10T22:57:18.500001</utc>
  <ra_j2000>0.740393528722</ra_j2000>
  <dec_j2000>5.78641590694</dec_j2000>
  <mag>11.0688955214</mag>
</meas>

<meas>
  <utc>2018-11-10T23:03:06.499995</utc>
  <ra_j2000>0.888541738338</ra_j2000>
  <dec_j2000>7.03265231497</dec_j2000>
  <mag>10.2358937709</mag>
</meas>

<meas>
  <utc>2018-11-10T23:05:42.500002</utc>
  <ra_j2000>0.955591973177</ra_j2000>
  <dec_j2000>7.5832430461</dec_j2000>
  <mag>10.86206725</mag>
</meas>

<meas>
  <utc>2018-11-10T23:06:48.499999</utc>
  <ra_j2000>0.984093767077</ra_j2000>
  <dec_j2000>7.81466175077</dec_j2000>
  <mag>10.3466108708</mag>
</meas>
</data>

我的问题是这些x轴上的值不一致。下面是我的Python脚本:

^{pr2}$

从而产生以下曲线图:

enter image description here

我打算稍后隐藏红色曲线(通过使用visibility=False),这里我绘制它只是为了看到x轴值的正确对齐,也就是说,两条曲线都必须(!)实际上是重叠的,因为相位角(x_phi)值依赖于相应的时间戳(x_ut)值,但是正如您可以清楚地看到的那样,只有开始和结束是正确对齐的,但是两者之间的大多数数据是不对齐的(相位曲线右移)。在

我做错什么了?在

起初,我假设相角(x_phi)在时间上是非线性变化的,因此这两条曲线的set_xlim()会以不同的方式拉伸它们,但这不是真的,我已经将x_phi与{}作了对比,并且有一个明显的线性变化:

enter image description here

提前感谢您的帮助!在

编辑:tel在下面的回答中已经证明了非线性。因此,我稍微改变一下我的问题。在

{{cd7}和

1)上x轴是自动反转的,从最小的值开始,尽管给出值的列表x_phi从最大值开始——如果不使用invert_axis(),如何避免这种反转呢?(在不同的情况下,x_phi列表中的值总是要么增加要么只有减少)

2)总共有3个列表:x_utx_phi和{};我只需要绘制曲线y_brightnessx_ut之间的曲线,另外还要使x_phi(带ticker.MultipleLocator(1))的值与x_ut中的相应时间矩值对齐——我该怎么做?在

我的问题与此类似: How do I align gridlines for two y-axis scales using Matplotlib? 但在我的例子中,上x轴的记号之间没有线性间距,所以我不能使用这个解决方案。在

同样,这个问题也涉及一个类似的问题: trouble aligning ticks for matplotlib twinx axes 但是在我的例子中,我不知道如何表达两个x轴之间的关系,因为数据类型非常不同:datetime和float。它们之间唯一的关系是一对一,即x_ut中的第一个值与{}中的第一个值相关,第二个值到第二个值,依此类推;这种关系是非线性的。在

编辑2:我上一次编辑中的数字1)现在解决了。对于剩下的问题,看起来我必须使用register_scale()来重新缩放相对于主x轴的次要x轴。为此,我还必须定义matplotlib.scale.ScaleBase的子类。到目前为止,我只找到了两个(对我来说)复杂的例子:

https://matplotlib.org/examples/api/custom_scale_example.html
https://stackoverrun.com/es/q/8578801(西班牙语,但代码中有英文注释)

我不确定我是否能自己实现这一点,所以我仍在寻求帮助。在


Tags: 编辑列表matplotlib时间绘制曲线dec例子
2条回答

你的绘图程序看起来是正确的。相反,问题似乎是在时间和相角之间的关系中,的线性偏差(非常小)。您可以通过在时间与角度图上叠加一条黑色直线来查看它(单击下面以在单独的窗口中打开并放大以清楚地看到):

enter image description here

下面是一个突出显示偏差的缩放:

enter image description here

使两个x轴对齐的唯一方法是:

  • 操纵数据。在
  • 操纵第二个x轴的比例使其不一致。使图上49度到48度之间的实际距离与图上45度到44度之间的实际距离不同,以此类推。在

这两个都是个坏主意™️,你不应该做任何一个。您需要按原样绘制数据,而不是试图用巧妙的技巧隐藏任何不一致之处。任何不足之处都可以被认为是学术上的不诚实。在

你唯一的选择就是弄清为什么时间和角度不符合你的期望。这可能是代码中的问题,可能是您在get_phase_angle中使用的公式中的问题。或者它可能是底层数据集中的问题,例如,如果度测量中有一些噪声。或者,事实上,时间和角度没有线性关系。毕竟,地球并不是完全圆的。在

耶!在没有定义新的scale类的情况下,我成功地获得了所需的结果!以下是在脚本中根据问题添加/修改的相关代码部分(变量step稍后将从用户命令行输入中读取,或者我可能会找到另一种自动设置滴答频率的方法):

x_ut = []
x_phi = []
x_phi_ticks = []
x_phi_ticklabels = []
y_brightness = []

# populate lists for the phase angle ticks and labels

i = 0
step = 15
while i <= (len(x_ut)-step):
    x_phi_ticks.append(x_ut[i])
    x_phi_ticklabels.append(x_phi[i])
    i += step
x_phi_ticks.append(x_ut[-1])
x_phi_ticklabels.append(x_phi[-1])

# plot'em all

fig, ax1 = plt.subplots()

ax1.plot(x_ut, y_brightness, marker='o', label='apparent brightness')
ax1.xaxis.set_major_locator(dates.MinuteLocator(interval=1))
ax1.xaxis.set_major_formatter(dates.DateFormatter('%H:%M'))
ax1.tick_params(axis='x', rotation=45)
ax1.minorticks_on()
ax1.legend()
ax1.grid(which='major', linestyle='-', color='#000000')
ax1.grid(which='minor', linestyle=' ')
ax1.set_xlabel('time [h:m, UT]')
ax1.set_ylabel('apparent brightness [mag, CR]')

ax2 = ax1.twiny()
ax2.set_xlim(ax1.get_xlim())
ax2.set_xticks(x_phi_ticks)
ax2.set_xticklabels(x_phi_ticklabels)
ax2.set_xlabel('phase angle (phi) [deg]')

plt.gca().invert_yaxis()
plt.tight_layout(pad=0)
plt.show()

enter image description here

相关问题 更多 >