Sometimes, as part of a quick exploratory data analysis, you may want to make a single plot containing two variables with different scales. Show One of the options is to make a single plot with two different y-axis, such that the y-axis on the left is for one variable and the y-axis on the right is for the y-variable. If you try to plot the two variables on a same plot without having two different y-axis, the plot would not really make sense. If the variables have very different scales, you’ll want to make sure that you plot them in different twin Axes objects. These objects can share one axis (for example, the time, or x-axis) while not sharing the other (the y-axis). To create a twin Axes object that shares the x-axis, we use the twinx method. Let us import Pandas. # import pandas import pandas as pd We will use gapminder data from Carpentries to make the plot with two different y-axis on the same plot. # Carpentries link for gapminder data data_url = 'http://bit.ly/2cLzoxH' #load gapminder data from url as pandas dataframe gapminder = pd.read_csv(data_url) print(gapminder.head(3)) Let us subset gapminder data by using Pandas query() function to filter for rows with United States. gapminder_us = gapminder[gapminder.country=="United States"] We are interested in making a plot of how lifeExp & gdpPercap changes over the years. The variable on x-axis is year and on y-axis we are interested in lifeExp & gdpPercap. Naively, let us plot both on the same plot with a single y-axis. # create figure and axis objects with subplots() fig,ax=plt.subplots() ax.plot(gapminder_us.year, gapminder_us.lifeExp, marker="o") ax.set_xlabel("year") ax.set_ylabel("lifeExp") ax.plot(gapminder_us.year, gapminder_us["gdpPercap"], marker="o") plt.show() We can immediately see that this is a bad idea. The line for lifeExp over years is flat and really low. We don’t see any variation in it because of the scale of gdpPercap values. Plotting variables of different scaleOne of the solutions is to make the plot with two different y-axes. The way to make a plot with two different y-axis is to use two different axes objects with the help of twinx() function. We first create figure and axis objects and make a first plot. In this example, we plot year vs lifeExp. And we also set the x and y-axis labels by updating the axis object. # create figure and axis objects with subplots() fig,ax = plt.subplots() # make a plot ax.plot(gapminder_us.year, gapminder_us.lifeExp, color="red", marker="o") # set x-axis label ax.set_xlabel("year", fontsize = 14) # set y-axis label ax.set_ylabel("lifeExp", color="red", fontsize=14) Next we use twinx() function to create the second axis object “ax2”. Now we use the second axis object “ax2” to make plot of the second y-axis variable and update their labels. # twin object for two different y-axis on the sample plot ax2=ax.twinx() # make a plot with different y-axis using second axis object ax2.plot(gapminder_us.year, gapminder_us["gdpPercap"],color="blue",marker="o") ax2.set_ylabel("gdpPercap",color="blue",fontsize=14) plt.show() # save the plot as a file fig.savefig('two_different_y_axis_for_single_python_plot_with_twinx.jpg', format='jpeg', dpi=100, bbox_inches='tight') Then we can display the plot with plt.show() as before. Now we have what we wanted. A plot with with different y-axis made with twinx in matplotlib. This definitely help us understand the relationship of the two variables against another. We can see that both lifeExp and gdpPerCap have increased over the years. Plot with two different y-axis with twinx in PythonAlthough a plot with two y-axis does help see the pattern, personally I feel this is bit cumbersome. A better solution to use the idea of “small multiples”, two subplots with same x-axis. We will see an example of that soon. Sometimes we want a 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 import matplotlib.pyplot as plt import numpy as np import datetime import matplotlib.dates as mdates from matplotlib.ticker import 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() 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. 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 one_over(x): """Vectorized 1/x, treating x==0 manually""" x = np.array(x).astype(float) near_zero = np.isclose(x, 0) x[near_zero] = np.inf x[~near_zero] = 1 / x[~near_zero] return x # the function "1/x" is its own inverse inverse = one_over secax = ax.secondary_xaxis('top', functions=(one_over, inverse)) secax.set_xlabel('period [s]') plt.show() 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. Note In order to properly handle the data margins, the mapping functions ( In the specific case of the numpy linear interpolation, 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 coordinate to another data-derived coordinate. # 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() A final example translates np.datetime64 to yearday on the x axis and from Celsius to Fahrenheit on the y axis. Note the addition of a third y axis, and that it can be placed using a float for the location argument How do I make a graph with two Y axis in Matplotlib?The easiest way to create a Matplotlib plot with two y axes is to use the twinx() function.
How do you make a graph with two different Y axis in Python?The way to make a plot with two different y-axis is to use two different axes objects with the help of twinx() function. We first create figure and axis objects and make a first plot. In this example, we plot year vs lifeExp. And we also set the x and y-axis labels by updating the axis object.
How to plot two y values in matplotlib?How to plot single data with two Y-axes (two units) in Matplotlib.... Set the figure size and adjust the padding between and around the subplots.. Create speed and acceleration data points using numpy.. Add a subplot to the current figure.. Plot speed data points using plot() method.. Create a twin Axes sharing the X-axis.. |