Dual Y-Axis Plots in Matplotlib

Plots with two y-axes are useful when you need to visualize two datasets with different y-scales on the same plot. This can help in comparing and analyzing trends or patterns that scale differently. In Matplotlib, creating a plot with a secondary y-axis is straightforward using the `twinx()` method.

This tutorial will guide you through creating and customizing plots with two y-axes using the `matplotlib` library.

### Basic Dual Y-Axis Plot

Let's start by creating a simple plot with two y-axes.

import matplotlib.pyplot as plt
import numpy as np

# Sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(x)

fig, ax1 = plt.subplots()

# Primary y-axis
ax1.plot(x, y1, 'g-', label='sin(x)')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('sin(x)')

# Create a twin Axes sharing the xaxis
ax2 = ax1.twinx()  

# Secondary y-axis
ax2.plot(x, y2, 'b--', label='exp(x)')
ax2.set_ylabel('exp(x)')

plt.title('Dual Y-Axis Plot')
plt.show()
- **`ax1.twinx()`** creates a secondary y-axis that shares the same x-axis as the primary y-axis.
- **`ax1.plot(x, y1, 'g-', label='sin(x)')`** plots data on the primary y-axis with green color.
- **`ax2.plot(x, y2, 'b--', label='exp(x)')`** plots data on the secondary y-axis with blue color.

### Customizing the Dual Y-Axis Plot

In this example, we’ll create a dual y-axis plot and add some customizations (legens and tick labels) to make it easier to interpret:

- Primary y-axis (green): Displays the sine function (sin(x)) on the left axis. The plot is green to match the color of the tick labels, creating a clear association between the axis and the plotted data.
- Secondary y-axis (blue): Displays the exponential function (exp(x)) on the right axis. The plot is in blue with corresponding blue tick labels, helping to distinguish it from the primary y-axis.
- Legends: Each plot has its own legend, with the sine function's legend in the upper left and the exponential function’s legend in the upper right, keeping them separate and easy to identify.

import matplotlib.pyplot as plt
import numpy as np

# Sample data
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(x)

fig, ax1 = plt.subplots()

# Primary y-axis
ax1.plot(x, y1, 'g-', label='sin(x)')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('sin(x)', color='g')
ax1.tick_params(axis='y', labelcolor='g')

# Create a twin Axes sharing the xaxis
ax2 = ax1.twinx()  

# Secondary y-axis
ax2.plot(x, y2, 'b--', label='exp(x)')
ax2.set_ylabel('exp(x)', color='b')
ax2.tick_params(axis='y', labelcolor='b')

# Adding legends
ax1.legend(loc='upper left')
ax2.legend(loc='upper right')

plt.title('Customized Dual Y-Axis Plot')
plt.show()
- **`ax1.tick_params(axis='y', labelcolor='g')`** and **`ax2.tick_params(axis='y', labelcolor='b')`** set the tick label colors to match the plot lines.
- **`ax1.legend(loc='upper left')`** and **`ax2.legend(loc='upper right')`** position the legends appropriately.

### Practical Example: Temperature and Precipitation

Here’s a practical example comparing temperature and precipitation data.

import matplotlib.pyplot as plt
import numpy as np

# Sample data
months = np.arange(1, 13)
temperature = np.array([30, 32, 45, 55, 70, 80, 85, 88, 77, 64, 50, 35])
precipitation = np.array([2.3, 2.6, 4.1, 3.2, 3.8, 3.6, 3.7, 2.7, 2.5, 2.9, 3.4, 3.1])

fig, ax1 = plt.subplots()

# Primary y-axis (Temperature)
ax1.plot(months, temperature, 'r-o', label='Temperature (°F)')
ax1.set_xlabel('Month')
ax1.set_ylabel('Temperature (°F)', color='r')
ax1.tick_params(axis='y', labelcolor='r')

# Create a twin Axes sharing the xaxis (Precipitation)
ax2 = ax1.twinx()

# Secondary y-axis (Precipitation)
ax2.bar(months, precipitation, color='b', alpha=0.6, label='Precipitation (in)')
ax2.set_ylabel('Precipitation (in)', color='b')
ax2.tick_params(axis='y', labelcolor='b')

# Adding legends
ax1.legend(loc='upper center')
ax2.legend(loc='upper right')

plt.title('Monthly Temperature and Precipitation')
fig.tight_layout()  # Adjust layout to prevent overlap

plt.show()
- **`ax2.bar(months, precipitation, color='b', alpha=0.6, label='Precipitation (in)')`** creates a bar plot for precipitation data on the secondary y-axis.
- **`ax1.plot(months, temperature, 'r-o', label='Temperature (°F)')`** creates a line plot for temperature data on the primary y-axis.


### Conclusion

Creating plots with two y-axes in Matplotlib allows you to visualize datasets with different y-scales on the same plot for convenient comparative analysis.