两个对应的y轴

时间:2014-06-20 10:30:48

标签: python matplotlib

我正在尝试用两个相应的y轴制作一个图。我想要的是在左侧y轴上的一个单位中的值(例如米)和在左侧y轴上的另一个单位(例如英寸)中的相应值。 在这种情况下,我设法用米和英寸来做到这一点。

然而,当转换不像只是乘以某种东西那么明显时,事情就不那么容易了。 在我的情况下,我试图绘制通量和幅度。从通量到数量的公式是: 23.9 - log(通量)。

当我绘制米和英寸时起作用的东西不再起作用了。 这是我的代码:

host = host_subplot(111)
host.set_xlim((0.1,5)) 
host.set_ylim((1.,50.))

par1 = host.twinx()
par1.set_ylim((23.899999999999999, 19.652574989159952)) # Converting the ylim from flux to mag

host.set_xlabel('Wavelength (Microns)')
host.set_ylabel('Flux density ($\mu$Jy)')
par1.set_ylabel("Magnitude ")

host.errorbar(x, flux, fmt='rx' , xerr=errx, yerr = errorFlux)
par1.errorbar(x, mag, fmt='bx', xerr=errx, yerr=errorMag)

如果这有效,那么两个图应该叠加,但它们不会(并且再次,我做了类似的工作,从米到英寸)。我怀疑这与日志有关,但是当设置比例进行记录时更糟糕。

2 个答案:

答案 0 :(得分:0)

试试这个,取自:http://matplotlib.org/examples/api/two_scales.html 我把我的版本放在下面。

我刚刚制作了一些指数增长数据的数据集。当然,轴可以更精确地摆弄,比如创建自己的刻度,范围和刻度标记;您所要做的就是花一些时间在线做一些示例并阅读API文档。另外,我会向您指出这个资源http://nbviewer.ipython.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-4-Matplotlib.ipynb以获得一些好的例子。

from numpy import *
import matplotlib.pyplot as plt


x_data = arange(0,100,.1)
y1_data = x_data**10
y2_data = x_data**4


fig, ax1 = plt.subplots(nrows=1, ncols=1)
ax1.set_yscale('linear')
ax1.plot(x_data,y1_data,'b-')
ax1.set_xlabel("Unitless X's")

ax1.set_ylabel('Linear Scale', color='b')
for tl in ax1.get_yticklabels():
    tl.set_color('b')

ax2 = ax1.twinx()
ax2.plot(x_data,y2_data,'r.')
ax2.set_ylabel("Log Scale", color='r')
ax2.set_yscale('log')
for tl in ax2.get_yticklabels():
    tl.set_color('r')
plt.show()

答案 1 :(得分:0)

所以我终于通过在matplotlib中创建一个新的比例来实现这一目标。它可以改进,但这是我的类定义,基于http://matplotlib.org/examples/api/custom_scale_example.html

import numpy as np
import matplotlib.pyplot as plt

from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms

class MagScale(mscale.ScaleBase):
    name = 'mag'

    def __init__(self, axis, **kwargs):
        mscale.ScaleBase.__init__(self)
        self.thresh = None #thresh

    def get_transform(self):
        return self.MagTransform(self.thresh)

    def set_default_locators_and_formatters(self, axis):
        pass

    class MagTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, mag):
            return 10**((np.array(mag) -1)/(-2.5))

        def inverted(self):
            return MagScale.InvertedMagTransform(self.thresh)

    class InvertedMagTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, flux):
            return -2.5 * np.log10(np.array(flux)) + 1.

        def inverted(self):
            return MagScale.MagTransform(self.thresh)



def flux_to_mag(flux):
    return  -2.5 * np.log10(flux) + 1


mscale.register_scale(MagScale)

这是一个有效的例子:

x    = np.arange(20.)
flux = x * 2 + 1
mag  = flux_to_mag(flux)

MagTransform = MagScale.InvertedMagTransform(0)


fig = plt.figure()
ax_flux = fig.add_subplot(111)

ax_flux.plot(x, flux,'-')
ax_flux.set_ylim([1,40])
ax_flux.set_ylabel('flux')

ax_mag  = ax_flux.twinx()
ax_mag.set_ylim(MagTransform.transform_non_affine(ax_flux.get_ylim())) #There may be an easier to do this.
ax_mag.set_yscale('mag')

ax_mag.plot(x,mag,'+')
plt.show()