How to Create a Matplotlib Plot with Two Y Axes?

How to Easily Create a Matplotlib Plot with Dual Y Axes

Visualizing datasets that contain two variables measured on fundamentally different scales presents a significant challenge when utilizing standard plotting techniques. When one metric registers in the tens and the other in the thousands, forcing them onto a single Y-axis results in a visualization where the lower-magnitude data appears flat, effectively obscuring critical trends. To overcome this limitation, the application of a dual Y-axis plot is essential. This technique, expertly implemented using the Matplotlib library in Python, allows two distinct data series to share a common X-axis while each is accurately mapped to its own corresponding vertical scale.

The methodology for creating a plot with two Y axes is highly efficient, leveraging Matplotlib’s powerful object-oriented interface. The process involves establishing a primary subplot, defining the first dataset on the initial axis, and then employing a specialized function to clone the X-axis, generating a second, independent Y-axis. This secondary axis is indispensable for displaying the magnitude and variability of the secondary dataset without visually distorting the primary series.

This guide provides an expert, step-by-step walkthrough focusing on how to generate such visualizations effectively. We will concentrate on using the core function, pyplot.twinx(), which serves as the fundamental link between the two vertical scales in Matplotlib, demonstrating its utility using realistic data structured within pandas DataFrames. Our aim is to ensure that you can produce clean, informative dual-axis plots that accurately convey complex relationships across multivariate data.


The easiest and most Pythonic way to create a Matplotlib plot with two Y axes is to use the pyplot.twinx() function, which automatically handles the synchronization of the X-axis across both vertical scales.

The following comprehensive example shows how to utilize this essential function in practice, covering data preparation and advanced visualization styling.

Preparing Bivariate Data for Dual-Axis Visualization

Effective data visualization starts with proper data preparation. In Python’s data analysis ecosystem, this invariably means structuring the information within pandas DataFrames, which are highly optimized for handling time-series and comparative datasets. For a dual-axis plot, we require two datasets that share a common independent variable (the X-axis), but possess dependent variables (the Y-axes) with significantly divergent scales.

Imagine a business analytics scenario where we need to concurrently monitor annual Sales figures (typically high dollar amounts) and the total number of Leads generated (typically low integer counts) over a ten-year timeline. If these were plotted together on a single axis scaled to accommodate the high Sales values, the subtle fluctuations in the low-value Leads data would be rendered almost invisible or flatlined near the zero baseline. This comparison necessitates the use of two scales.

The code below initializes the two required DataFrames. Both share the common ‘year’ column, ensuring that our comparisons are temporally aligned:

import pandas as pd

#create DataFrames
df1 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                    'sales': [14, 16, 19, 22, 24, 25, 24, 24, 27, 30]})

df2 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                    'leads': [4, 4, 4, 5, 4, 5, 7, 8, 5, 3]})

The first DataFrame (df1) contains the high-magnitude ‘sales’ data, while the second (df2) holds the low-magnitude ‘leads’ data. Both are perfectly aligned by the ‘year’ column, which runs from 1 to 10. This structure confirms the data is ready for plotting onto a shared X-axis using separate Y-axis scales.

Establishing the Primary and Secondary Axes using twinx()

The foundation of our Matplotlib plot begins with the creation of the figure and the primary axes object. We utilize plt.subplots() for this purpose, obtaining the Figure object (fig) and the initial Axes object (ax). This primary axis will host the first data series—in our case, Sales.

Once the primary data series (Sales) is plotted on ax and labeled appropriately, the critical step of introducing the second axis is performed using ax2 = ax.twinx(). This function does exactly what its name implies: it creates a new Axes object, ax2, which is a twin of ax in the horizontal direction. This new axis object is completely independent in its vertical scaling but shares the exact same X-axis positions, ensuring perfect alignment between the two metrics over time.

To maintain clear data communication, it is imperative to use distinct colors for each plotted line and ensure these colors are reflected in the corresponding axis labels. This coloring scheme instantly signals to the reader which line corresponds to the left Y-axis (primary) and which corresponds to the right Y-axis (secondary).

import matplotlib.pyplot as plt

#define colors to use for visual differentiation
col1 = 'steelblue'
col2 = 'red'

#define subplots (Figure and primary Axes)
fig,ax = plt.subplots()

#add first line (Sales) to the primary plot
ax.plot(df1.year, df1.sales, color=col1)

#add shared x-axis label
ax.set_xlabel('Year', fontsize=14)

#add primary y-axis label (Sales)
ax.set_ylabel('Sales', color=col1, fontsize=16)

#define second y-axis that shares x-axis with current plot
ax2 = ax.twinx()

#add second line (Leads) to the secondary plot
ax2.plot(df2.year, df2.leads, color=col2)

#add secondary y-axis label (Leads)
ax2.set_ylabel('Leads', color=col2, fontsize=16)

Matplotlib with two y axes

Interpreting the Basic Dual Axis Visualization

The resulting visualization is a consolidated view of two disparate datasets. The Y-axis on the left, identified by the steelblue color, displays the total Sales volume, scaled appropriately for its range (14 to 30). The blue line, therefore, must be interpreted exclusively against this left scale.

Conversely, the Y-axis on the right side of the plot, highlighted in red, charts the total Leads generated annually, scaled much lower (typically 3 to 8). The red line should only be interpreted against this right scale. The common X-axis ensures that any observed visual relationship or trend (e.g., when the red line spikes, does the blue line follow?) is temporally accurate.

This visualization technique allows analysts to observe potential correlations or divergences that would be invisible if the data were forced onto a single, overly broad scale. The clear visual separation provided by the axes positioning and coordinated color coding ensures that readers can accurately distinguish between the two metrics without confusion.

Advanced Styling: Utilizing Marker and Linewidth Arguments

While the initial plot is functional, enhancing its visual quality is paramount for professional reporting. Matplotlib offers granular control over line appearance through optional parameters passed directly to the .plot() method. Specifically, the linewidth and marker arguments are highly effective for improving clarity in line charts.

The linewidth argument controls the thickness of the line. Increasing this value (e.g., setting it to 3) makes the data trend visually bolder and easier to follow, particularly when multiple lines are plotted close together. Furthermore, the marker argument allows the developer to specify a symbol that will be plotted exactly at each measurement point, thereby highlighting the discrete data points used to form the continuous line. Using ‘o’ for a circle is a standard convention.

By applying these styling attributes to both the primary and secondary plotting calls, we ensure that both Sales and Leads benefit from improved visibility and precision. This transformation shifts the visualization from a basic chart to a professional-grade analytical tool.

import matplotlib.pyplot as plt

#define colors to use
col1 = 'steelblue'
col2 = 'red'

#define subplots
fig,ax = plt.subplots()

#add first line to plot, now with marker and linewidth
ax.plot(df1.year, df1.sales, color=col1, marker='o', linewidth=3)

#add x-axis label
ax.set_xlabel('Year', fontsize=14)

#add y-axis label
ax.set_ylabel('Sales', color=col1, fontsize=16)

#define second y-axis that shares x-axis with current plot
ax2 = ax.twinx()

#add second line to plot, now with marker and linewidth
ax2.plot(df2.year, df2.leads, color=col2, marker='o', linewidth=3)

#add second y-axis label
ax2.set_ylabel('Leads', color=col2, fontsize=16)

As demonstrated by the output image, both data lines are now clearly distinguished by their increased linewidth, and the addition of the ‘o’ marker precisely indicates the data point corresponding to each year. This level of detail confirms that the plot is not only technically valid but also optimized for analytical rigor.

Ethical Considerations and Best Practices for Dual Y-Axes

While dual Y-axis plots are powerful, they are often criticized in data visualization circles because they carry the risk of misuse, potentially leading to misinterpretation. The fundamental ethical challenge lies in the arbitrary scaling of the secondary axis. By manually setting the limits of the right Y-axis, one can visually exaggerate or minimize correlation, falsely implying a strong relationship or divergence that is not supported by the underlying statistics.

To ensure that your dual-axis plot is informative and trustworthy, adhere to the following best practices:

  • Ensure Visual Consistency: Always link the line color directly to the color of its corresponding axis labels and tick marks. This eliminates ambiguity regarding which scale applies to which dataset.
  • Use Meaningful Relationships Only: Reserve dual-axis plotting for variables that are inherently related, such as two metrics measured against a common time sequence, or input variables influencing a primary output variable. Plotting completely unrelated series (e.g., stock price and average monthly rainfall) can confuse and mislead.
  • Maintain Transparency: Clearly document the scaling choices used for both axes, especially if non-zero baselines are employed. The primary goal should always be accurate data representation, not persuasive visual distortion.

Advanced Matplotlib users might also explore further customization using methods like ax.tick_params() to control the color and size of tick labels, further reinforcing the visual distinction between the primary and secondary scales. Such meticulous attention to detail transforms a simple dual-axis chart into a reliable piece of statistical evidence.

Conclusion: Mastering Dual-Scale Visualization

Generating highly informative Matplotlib visualizations with two vertical axes is a core technique for comparative data analysis in Python. The methodology is robust, relying on the structured creation of axes objects using plt.subplots() and the essential linking mechanism provided by pyplot.twinx().

By diligently following the steps of data preparation, axis definition, and the application of customization parameters like marker and linewidth, you gain the ability to effectively compare metrics that span vastly different scales, such as sales volume versus lead count. Remember that successful visualization is a blend of technical accuracy and deliberate design choices, ensuring that the complex data relationships are communicated with maximum clarity and integrity.

Cite this article

stats writer (2025). How to Easily Create a Matplotlib Plot with Dual Y Axes. PSYCHOLOGICAL SCALES. Retrieved from https://scales.arabpsychology.com/stats/how-to-create-a-matplotlib-plot-with-two-y-axes/

stats writer. "How to Easily Create a Matplotlib Plot with Dual Y Axes." PSYCHOLOGICAL SCALES, 3 Dec. 2025, https://scales.arabpsychology.com/stats/how-to-create-a-matplotlib-plot-with-two-y-axes/.

stats writer. "How to Easily Create a Matplotlib Plot with Dual Y Axes." PSYCHOLOGICAL SCALES, 2025. https://scales.arabpsychology.com/stats/how-to-create-a-matplotlib-plot-with-two-y-axes/.

stats writer (2025) 'How to Easily Create a Matplotlib Plot with Dual Y Axes', PSYCHOLOGICAL SCALES. Available at: https://scales.arabpsychology.com/stats/how-to-create-a-matplotlib-plot-with-two-y-axes/.

[1] stats writer, "How to Easily Create a Matplotlib Plot with Dual Y Axes," PSYCHOLOGICAL SCALES, vol. X, no. Y, ص Z-Z, December, 2025.

stats writer. How to Easily Create a Matplotlib Plot with Dual Y Axes. PSYCHOLOGICAL SCALES. 2025;vol(issue):pages.

Download Post (.PDF)
Slide Up
x
PDF
Scroll to Top