How to Use Different Y-Axes on the Left and Right of a Matplotlib Plot
Use different y-axes on the left and right of a Matplotlib plot to effectively display multiple datasets with varying scales or units on the same graph. This technique, known as dual y-axis plotting, is a powerful way to visualize relationships between different variables that may have distinct ranges or measurements. In this comprehensive guide, we’ll explore various methods and best practices for creating plots with different y-axes on the left and right sides using Matplotlib.
Understanding the Need for Different Y-Axes
Before we dive into the implementation details of how to use different y-axes on the left and right of a Matplotlib plot, let’s discuss why this approach is valuable in data visualization.
- Comparing datasets with different scales: When you have two or more datasets with significantly different ranges, using a single y-axis may result in one dataset being compressed or difficult to read. By utilizing different y-axes, you can effectively display both datasets without sacrificing clarity.
-
Visualizing related variables with different units: In some cases, you may want to plot variables that are related but measured in different units. Using different y-axes allows you to show the relationship between these variables while maintaining their respective scales.
-
Enhancing data interpretation: By presenting multiple datasets on the same plot with different y-axes, you can facilitate easier comparison and analysis of trends, correlations, or patterns between the variables.
Now that we understand the importance of using different y-axes, let’s explore how to implement this technique using Matplotlib.
Basic Implementation of Different Y-Axes
To use different y-axes on the left and right of a Matplotlib plot, we’ll start with a basic implementation. This involves creating a primary y-axis on the left side and a secondary y-axis on the right side of the plot.
Here’s a simple example to demonstrate this concept:
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(x)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots()
# Plot data on the primary y-axis
ax1.plot(x, y1, color='blue', label='Sine Wave')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Sine Wave', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot data on the secondary y-axis
ax2.plot(x, y2, color='red', label='Exponential')
ax2.set_ylabel('Exponential', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
plt.show()
Output:
In this example, we use different y-axes on the left and right of a Matplotlib plot to display a sine wave and an exponential function. Let’s break down the key steps:
- We create the primary axis (
ax1
) usingplt.subplots()
. - We plot the sine wave on the primary y-axis and set its label and color.
- We create the secondary y-axis (
ax2
) usingax1.twinx()
. - We plot the exponential function on the secondary y-axis and set its label and color.
- We add a title and legend to complete the plot.
This basic implementation demonstrates how to use different y-axes on the left and right of a Matplotlib plot to display two datasets with different scales.
Customizing Y-Axis Scales and Limits
When you use different y-axes on the left and right of a Matplotlib plot, it’s often necessary to customize the scales and limits of each axis to ensure optimal visualization. Let’s explore how to adjust these properties for both the primary and secondary y-axes.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 100 * np.exp(x)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots()
# Plot data on the primary y-axis
ax1.plot(x, y1, color='blue', label='Sine Wave')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Sine Wave', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
ax1.set_ylim(-1.5, 1.5) # Set custom limits for the primary y-axis
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot data on the secondary y-axis
ax2.plot(x, y2, color='red', label='Exponential')
ax2.set_ylabel('Exponential', color='red')
ax2.tick_params(axis='y', labelcolor='red')
ax2.set_yscale('log') # Set logarithmic scale for the secondary y-axis
ax2.set_ylim(1, 1e6) # Set custom limits for the secondary y-axis
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with customized scales and limits:
- We set custom limits for the primary y-axis using
ax1.set_ylim(-1.5, 1.5)
. - We apply a logarithmic scale to the secondary y-axis using
ax2.set_yscale('log')
. - We set custom limits for the secondary y-axis using
ax2.set_ylim(1, 1e6)
.
By adjusting the scales and limits, we can ensure that both datasets are clearly visible and properly represented on their respective axes.
Adding Multiple Datasets to Each Y-Axis
When you use different y-axes on the left and right of a Matplotlib plot, you may want to display multiple datasets on each axis. This can be useful for comparing related variables or showing different aspects of the same data. Let’s explore how to add multiple datasets to each y-axis.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = 100 * np.exp(x)
y4 = 50 * np.log(x + 1)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots()
# Plot data on the primary y-axis
ax1.plot(x, y1, color='blue', label='Sine Wave')
ax1.plot(x, y2, color='cyan', label='Cosine Wave')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Trigonometric Functions', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot data on the secondary y-axis
ax2.plot(x, y3, color='red', label='Exponential')
ax2.plot(x, y4, color='orange', label='Logarithmic')
ax2.set_ylabel('Growth Functions', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with multiple datasets on each axis:
- We plot two trigonometric functions (sine and cosine) on the primary y-axis.
- We plot two growth functions (exponential and logarithmic) on the secondary y-axis.
- We use different colors for each dataset to improve visibility.
- We update the y-axis labels to reflect the groups of functions plotted on each axis.
By adding multiple datasets to each y-axis, we can create more complex and informative visualizations while still maintaining the benefits of using different scales on the left and right sides of the plot.
Styling and Formatting Dual Y-Axis Plots
When you use different y-axes on the left and right of a Matplotlib plot, it’s important to style and format the plot effectively to enhance readability and visual appeal. Let’s explore various styling techniques to improve the presentation of dual y-axis plots.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 100 * np.exp(x)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots(figsize=(10, 6))
# Plot data on the primary y-axis
ax1.plot(x, y1, color='#1f77b4', label='Sine Wave', linewidth=2)
ax1.set_xlabel('X-axis', fontsize=12)
ax1.set_ylabel('Sine Wave', color='#1f77b4', fontsize=12)
ax1.tick_params(axis='y', labelcolor='#1f77b4', labelsize=10)
ax1.grid(True, linestyle='--', alpha=0.7)
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot data on the secondary y-axis
ax2.plot(x, y2, color='#d62728', label='Exponential', linewidth=2)
ax2.set_ylabel('Exponential', color='#d62728', fontsize=12)
ax2.tick_params(axis='y', labelcolor='#d62728', labelsize=10)
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com', fontsize=14, fontweight='bold')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', fontsize=10)
# Adjust layout and display the plot
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with enhanced styling and formatting:
- We set a larger figure size using
figsize=(10, 6)
for better visibility. - We use custom colors (
#1f77b4
and#d62728
) for the lines and axis labels. - We increase the line width to 2 for both plots using
linewidth=2
. - We adjust font sizes for labels, tick labels, and the title.
- We add a grid to the primary y-axis using
ax1.grid()
with custom style and transparency. - We use
plt.tight_layout()
to automatically adjust the plot layout.
These styling techniques help create a more visually appealing and professional-looking plot when using different y-axes on the left and right sides.
Handling Date and Time Data with Dual Y-Axes
When working with time series data, you may need to use different y-axes on the left and right of a Matplotlib plot to display multiple variables over time. Let’s explore how to handle date and time data in dual y-axis plots.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Generate sample data
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
temperature = 20 + 10 * np.sin(np.arange(len(dates)) * 2 * np.pi / 365)
rainfall = 50 + 30 * np.random.rand(len(dates))
# Create the figure and primary y-axis
fig, ax1 = plt.subplots(figsize=(12, 6))
# Plot temperature data on the primary y-axis
ax1.plot(dates, temperature, color='red', label='Temperature')
ax1.set_xlabel('Date')
ax1.set_ylabel('Temperature (°C)', color='red')
ax1.tick_params(axis='y', labelcolor='red')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot rainfall data on the secondary y-axis
ax2.bar(dates, rainfall, alpha=0.3, color='blue', label='Rainfall')
ax2.set_ylabel('Rainfall (mm)', color='blue')
ax2.tick_params(axis='y', labelcolor='blue')
# Format x-axis to show dates nicely
plt.gcf().autofmt_xdate()
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with date and time data:
- We generate sample temperature and rainfall data using Pandas date ranges.
- We plot the temperature data as a line on the primary y-axis.
- We plot the rainfall data as bars on the secondary y-axis.
- We use
plt.gcf().autofmt_xdate()
to automatically format the x-axis dates for better readability. - We adjust the plot layout using
plt.tight_layout()
to prevent overlapping labels.
This approach allows you to effectively visualize multiple time series with different scales on the same plot.
Creating Stacked Plots with Dual Y-Axes
When you use different y-axes on the left and right of a Matplotlib plot, you can also create stacked plots to show cumulative data alongside individual variables. Let’s explore how to combine stacked plots with dual y-axes.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.arange(10)
y1 = np.random.randint(1, 10, 10)
y2 = np.random.randint(1, 10, 10)
y3 = np.random.randint(1, 10, 10)
y4 = np.cumsum(y1 + y2 + y3)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots(figsize=(10, 6))
# Plot stacked data on the primary y-axis
ax1.bar(x, y1, label='Category 1')
ax1.bar(x, y2, bottom=y1, label='Category 2')
ax1.bar(x, y3, bottom=y1+y2, label='Category 3')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Individual Values')
ax1.legend(loc='upper left')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot cumulative data on the secondary y-axis
ax2.plot(x, y4, color='red', linewidth=2, label='Cumulative')
ax2.set_ylabel('Cumulative Values', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend for the secondary y-axis
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines2, labels2, loc='upper right')
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with stacked bars and a cumulative line:
- We create a stacked bar plot using three categories on the primary y-axis.
- We calculate and plot the cumulative sum of all categories on the secondary y-axis.
- We use different colors and styles for the stacked bars and the cumulative line.
- We add separate legends for the primary and secondary y-axes.
This approach allows you to visualize both individual category values and their cumulative sum on the same plot, using different scales for clarity.
Handling Categorical Data with Dual Y-Axes
When you use different y-axes on the left and right of a Matplotlib plot, you may encounter situations where one axis represents categorical data while the other represents numerical data. Let’s explore how to handle this scenario effectively.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
categories = ['A', 'B', 'C', 'D', 'E']
values1 = np.random.randint(1, 100, 5)
values2 = np.random.rand(5)
# Create the figure and primary y-axis
fig, ax1 = plt.subplots(figsize=(10, 6))
# Plot bar chart on the primary y-axis
ax1.bar(categories, values1, color='skyblue')
ax1.set_xlabel('Categories')
ax1.set_ylabel('Values (Primary)', color='skyblue')
ax1.tick_params(axis='y', labelcolor='skyblue')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot line chart on the secondary y-axis
ax2.plot(categories, values2, color='red', marker='o', linewidth=2)
ax2.set_ylabel('Values (Secondary)', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Adjust layout and display the plot
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot with categorical data:
- We create a bar chart using categorical data on the primary y-axis.
- We plot a line chart with numerical data on the secondary y-axis.
- We use different colors for each axis to distinguish between the two datasets.
- We adjust the layout using
plt.tight_layout()
to prevent overlapping labels.
This approach allows you to effectively combine categorical and numerical data on the same plot using different y-axes.
Creating Subplots with Dual Y-Axes
When you need to compare multiple datasets with different scales, you might want to create subplots, each with its own set of different y-axes on the left and right. Let’s explore how to create a grid of subplots, each utilizing dual y-axes.
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(x)
y3 = np.log(x + 1)
y4 = x**2
# Create a 2x2 grid of subplots
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))
# Subplot 1
ax1.plot(x, y1, color='blue', label='Sine')
ax1.set_ylabel('Sine', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
ax1_twin = ax1.twinx()
ax1_twin.plot(x, y2, color='red', label='Exponential')
ax1_twin.set_ylabel('Exponential', color='red')
ax1_twin.tick_params(axis='y', labelcolor='red')
ax1.set_title('Sine vs Exponential')
# Subplot 2
ax2.plot(x, y3, color='green', label='Logarithmic')
ax2.set_ylabel('Logarithmic', color='green')
ax2.tick_params(axis='y', labelcolor='green')
ax2_twin = ax2.twinx()
ax2_twin.plot(x, y4, color='orange', label='Quadratic')
ax2_twin.set_ylabel('Quadratic', color='orange')
ax2_twin.tick_params(axis='y', labelcolor='orange')
ax2.set_title('Logarithmic vs Quadratic')
# Subplot 3
ax3.plot(x, y1, color='purple', label='Sine')
ax3.set_ylabel('Sine', color='purple')
ax3.tick_params(axis='y', labelcolor='purple')
ax3_twin = ax3.twinx()
ax3_twin.plot(x, y3, color='brown', label='Logarithmic')
ax3_twin.set_ylabel('Logarithmic', color='brown')
ax3_twin.tick_params(axis='y', labelcolor='brown')
ax3.set_title('Sine vs Logarithmic')
# Subplot 4
ax4.plot(x, y2, color='cyan', label='Exponential')
ax4.set_ylabel('Exponential', color='cyan')
ax4.tick_params(axis='y', labelcolor='cyan')
ax4_twin = ax4.twinx()
ax4_twin.plot(x, y4, color='magenta', label='Quadratic')
ax4_twin.set_ylabel('Quadratic', color='magenta')
ax4_twin.tick_params(axis='y', labelcolor='magenta')
ax4.set_title('Exponential vs Quadratic')
# Add a main title
fig.suptitle('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com', fontsize=16)
# Adjust layout and display the plot
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of multiple Matplotlib subplots:
- We create a 2×2 grid of subplots using
plt.subplots(2, 2)
. - For each subplot, we plot one dataset on the primary y-axis and another on the secondary y-axis.
- We use different color schemes for each subplot to distinguish between the datasets.
- We add individual titles to each subplot and a main title for the entire figure.
- We use
plt.tight_layout()
to automatically adjust the layout and prevent overlapping.
This approach allows you to compare multiple pairs of datasets with different scales in a single figure, each utilizing its own set of dual y-axes.
Animating Plots with Dual Y-Axes
When you use different y-axes on the left and right of a Matplotlib plot, you can create dynamic visualizations by animating the data over time. Let’s explore how to create an animated plot with dual y-axes using Matplotlib’s animation functionality.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
# Generate initial data
t = np.linspace(0, 2*np.pi, 100)
x = np.sin(t)
y = np.cos(t)
# Create the figure and axes
fig, ax1 = plt.subplots()
# Create the primary y-axis
line1, = ax1.plot(t, x, color='blue', label='Sine')
ax1.set_xlabel('Time')
ax1.set_ylabel('Sine', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
# Create the secondary y-axis
ax2 = ax1.twinx()
line2, = ax2.plot(t, y, color='red', label='Cosine')
ax2.set_ylabel('Cosine', color='red')
ax2.tick_params(axis='y', labelcolor='red')
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines = [line1, line2]
ax1.legend(lines, [l.get_label() for l in lines], loc='upper right')
# Animation update function
def update(frame):
line1.set_ydata(np.sin(t + frame/10))
line2.set_ydata(np.cos(t + frame/10))
return line1, line2
# Create the animation
ani = animation.FuncAnimation(fig, update, frames=100, interval=50, blit=True)
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot in an animated visualization:
- We create initial sine and cosine data.
- We set up the primary and secondary y-axes with their respective plots.
- We define an update function that modifies the y-data for both lines in each frame.
- We create an animation using
animation.FuncAnimation()
.
This approach allows you to create dynamic visualizations that show how two related variables change over time, each with its own scale on opposite sides of the plot.
Handling Missing Data in Dual Y-Axis Plots
When you use different y-axes on the left and right of a Matplotlib plot, you may encounter situations where one or both datasets contain missing values. Let’s explore how to handle missing data effectively in dual y-axis plots.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Generate sample data with missing values
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
temperature = 20 + 10 * np.sin(np.arange(len(dates)) * 2 * np.pi / 365)
rainfall = 50 + 30 * np.random.rand(len(dates))
# Introduce missing values
temperature[50:100] = np.nan
rainfall[150:200] = np.nan
# Create a DataFrame
df = pd.DataFrame({'Date': dates, 'Temperature': temperature, 'Rainfall': rainfall})
# Create the figure and primary y-axis
fig, ax1 = plt.subplots(figsize=(12, 6))
# Plot temperature data on the primary y-axis
ax1.plot(df['Date'], df['Temperature'], color='red', label='Temperature')
ax1.set_xlabel('Date')
ax1.set_ylabel('Temperature (°C)', color='red')
ax1.tick_params(axis='y', labelcolor='red')
# Create the secondary y-axis
ax2 = ax1.twinx()
# Plot rainfall data on the secondary y-axis
ax2.plot(df['Date'], df['Rainfall'], color='blue', label='Rainfall')
ax2.set_ylabel('Rainfall (mm)', color='blue')
ax2.tick_params(axis='y', labelcolor='blue')
# Format x-axis to show dates nicely
plt.gcf().autofmt_xdate()
# Add a title
plt.title('Use different y-axes on the left and right of a Matplotlib plot - how2matplotlib.com')
# Add a legend
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')
plt.tight_layout()
plt.show()
Output:
In this example, we demonstrate how to use different y-axes on the left and right of a Matplotlib plot while handling missing data:
- We generate sample temperature and rainfall data with intentionally introduced missing values.
- We create a Pandas DataFrame to store the data, which automatically handles missing values.
- We plot both datasets using their respective y-axes, and Matplotlib automatically skips the missing values.
- We use
plt.gcf().autofmt_xdate()
to format the x-axis dates for better readability.
This approach allows you to visualize datasets with missing values on dual y-axes without causing errors or distortions in the plot.
Conclusion
In this comprehensive guide, we’ve explored various aspects of how to use different y-axes on the left and right of a Matplotlib plot. We’ve covered basic implementation, customization of scales and limits, handling multiple datasets, styling and formatting, working with date and time data, creating stacked plots, dealing with categorical data, creating subplots, animating dual y-axis plots, and handling missing data.