两个对应的y轴

3
我正在尝试制作一个带有两个相应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)

如果这个方法有效,那么两个图应该重叠在一起,但是实际上它们没有(而且我曾经在将类似的内容从米转换为英寸时使其工作)。我猜测这与对数有关,但是当将比例尺设置为对数时,情况变得更糟。


可能是multiple axis in matplotlib with different scales的重复问题。 - Saullo G. P. Castro
1
实际上,这就是我在尝试做这件事时遇到的问题,并将其用作我的代码基础。不幸的是,在我的情况下,这并不起作用。 - Cehem
2个回答

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()

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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接