0

I am using python and matplotlib to try and recreate the dual axis in this chart. In Matplotlib how can I adjust the vertical position of each y axis?

enter image description here

Here is the code for a dual axis line chart:

import matplotlib.pyplot as plt

# Data for the x-axis
x = [1, 2, 3, 4, 5]

# Data for the primary y-axis
y1 = [10, 15, 7, 12, 9]

# Data for the secondary y-axis
y2 = [200, 150, 120, 180, 220]

# Create figure and axes objects
fig, ax1 = plt.subplots(figsize=(14,5))

# Plot the data for the primary y-axis
ax1.plot(x, y1, 'g-', label='Primary')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Primary Y-axis')
ax1.tick_params('y', colors='black')

# Create a second axes that shares the same x-axis
ax2 = ax1.twinx()

# Plot the data for the secondary y-axis
ax2.plot(x, y2, 'b-', label='Secondary')
ax2.set_ylabel('Secondary Y-axis')
ax2.tick_params('y', colors='black')

# Add a legend
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right')

# Set the title and display the chart
plt.title('Dual Axis Line Chart')
plt.show()

Any ideas how I can modify this code to separate each line?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158

1 Answers1

1

You achieve this by tweaking the axes limits with ax.set_ylim().

You can do it by hand, but I think that the following will adapt pretty well:

# Set limits
def tweak_ylimits(ax1, ax2, y1, y2):
    y1, y2 = np.array(y1), np.array(y2)

    # Get the most "problematic" point
    def minmax_scale(y):
        vmin, vmax = y.min(), y.max()
        return (y - vmin) / (vmax - vmin)

    shift = (minmax_scale(y1) - minmax_scale(y2)).max()
    shift = min(shift, 0.9)

    # Make some room above y1 by setting new ylim max
    # (y1_max - y1_min) = shift * (y1_max_new - y1_min)
    y1_min, y1_max = ax1.get_ylim()
    y1_max_new = (y1_max - y1_min) / shift + y1_min

    # Make some room below y2 by setting new ylim min
    # (y2_max - y2_min) = (1 - shift) * (y2_max - y2_lim_min_new)
    y2_min, y2_max = ax2.get_ylim()
    y2_min_new = -((y2_max - y2_min) / (1 - shift) - y2_max)

    ax1.set_ylim([None, y1_max_new])
    ax2.set_ylim([y2_min_new, None])

tweak_ylimits(ax1, ax2, y1, y2)

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
paime
  • 2,901
  • 1
  • 6
  • 17