.. note::
    :class: sphx-glr-download-link-note

    Click :ref:`here <sphx_glr_download_gallery_subplots_axes_and_figures_secondary_axis.py>` to download the full example code
.. rst-class:: sphx-glr-example-title

.. _sphx_glr_gallery_subplots_axes_and_figures_secondary_axis.py:


==============
Secondary Axis
==============

Sometimes we want as secondary axis on a plot, for instance to convert
radians to degrees on the same plot.  We can do this by making a child
axes with only one axis visible via `.Axes.axes.secondary_xaxis` and
`.Axes.axes.secondary_yaxis`.  This secondary axis can have a different scale
than the main axis by providing both a forward and an inverse conversion
function in a tuple to the ``functions`` kwarg:


.. code-block:: python


    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    import matplotlib.dates as mdates
    from matplotlib.transforms import Transform
    from matplotlib.ticker import (
        AutoLocator, AutoMinorLocator)

    fig, ax = plt.subplots(constrained_layout=True)
    x = np.arange(0, 360, 1)
    y = np.sin(2 * x * np.pi / 180)
    ax.plot(x, y)
    ax.set_xlabel('angle [degrees]')
    ax.set_ylabel('signal')
    ax.set_title('Sine wave')


    def deg2rad(x):
        return x * np.pi / 180


    def rad2deg(x):
        return x * 180 / np.pi

    secax = ax.secondary_xaxis('top', functions=(deg2rad, rad2deg))
    secax.set_xlabel('angle [rad]')
    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_001.png
    :class: sphx-glr-single-img




Here is the case of converting from wavenumber to wavelength in a
log-log scale.

.. note ::

  In this case, the xscale of the parent is logarithmic, so the child is
  made logarithmic as well.



.. code-block:: python


    fig, ax = plt.subplots(constrained_layout=True)
    x = np.arange(0.02, 1, 0.02)
    np.random.seed(19680801)
    y = np.random.randn(len(x)) ** 2
    ax.loglog(x, y)
    ax.set_xlabel('f [Hz]')
    ax.set_ylabel('PSD')
    ax.set_title('Random spectrum')


    def forward(x):
        return 1 / x


    def inverse(x):
        return 1 / x

    secax = ax.secondary_xaxis('top', functions=(forward, inverse))
    secax.set_xlabel('period [s]')
    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_002.png
    :class: sphx-glr-single-img




Sometime we want to relate the axes in a transform that is ad-hoc from
the data, and is derived empirically.  In that case we can set the
forward and inverse transforms functions to be linear interpolations from the
one data set to the other.



.. code-block:: python


    fig, ax = plt.subplots(constrained_layout=True)
    xdata = np.arange(1, 11, 0.4)
    ydata = np.random.randn(len(xdata))
    ax.plot(xdata, ydata, label='Plotted data')

    xold = np.arange(0, 11, 0.2)
    # fake data set relating x co-ordinate to another data-derived co-ordinate.
    # xnew must be monotonic, so we sort...
    xnew = np.sort(10 * np.exp(-xold / 4) + np.random.randn(len(xold)) / 3)

    ax.plot(xold[3:], xnew[3:], label='Transform data')
    ax.set_xlabel('X [m]')
    ax.legend()


    def forward(x):
        return np.interp(x, xold, xnew)


    def inverse(x):
        return np.interp(x, xnew, xold)

    secax = ax.secondary_xaxis('top', functions=(forward, inverse))
    secax.xaxis.set_minor_locator(AutoMinorLocator())
    secax.set_xlabel('$X_{other}$')

    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_003.png
    :class: sphx-glr-single-img




A final example translates np.datetime64 to yearday on the x axis and
from Celsius to Farenheit on the y axis:



.. code-block:: python



    dates = [datetime.datetime(2018, 1, 1) + datetime.timedelta(hours=k * 6)
                for k in range(240)]
    temperature = np.random.randn(len(dates))
    fig, ax = plt.subplots(constrained_layout=True)

    ax.plot(dates, temperature)
    ax.set_ylabel(r'$T\ [^oC]$')
    plt.xticks(rotation=70)


    def date2yday(x):
        """
        x is in matplotlib datenums, so they are floats.
        """
        y = x - mdates.date2num(datetime.datetime(2018, 1, 1))
        return y


    def yday2date(x):
        """
        return a matplotlib datenum (x is days since start of year)
        """
        y = x + mdates.date2num(datetime.datetime(2018, 1, 1))
        return y

    secaxx = ax.secondary_xaxis('top', functions=(date2yday, yday2date))
    secaxx.set_xlabel('yday [2018]')


    def CtoF(x):
        return x * 1.8 + 32


    def FtoC(x):
        return (x - 32) / 1.8

    secaxy = ax.secondary_yaxis('right', functions=(CtoF, FtoC))
    secaxy.set_ylabel(r'$T\ [^oF]$')

    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_004.png
    :class: sphx-glr-single-img




------------

References
""""""""""

The use of the following functions and methods is shown in this example:



.. code-block:: python


    import matplotlib

    matplotlib.axes.Axes.secondary_xaxis
    matplotlib.axes.Axes.secondary_yaxis







.. _sphx_glr_download_gallery_subplots_axes_and_figures_secondary_axis.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download

     :download:`Download Python source code: secondary_axis.py <secondary_axis.py>`



  .. container:: sphx-glr-download

     :download:`Download Jupyter notebook: secondary_axis.ipynb <secondary_axis.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    Keywords: matplotlib code example, codex, python plot, pyplot
    `Gallery generated by Sphinx-Gallery
    <https://sphinx-gallery.readthedocs.io>`_
