I am trying make a plot with subplot for a list of pandas dataframes. Each dataframe-plot consists of a primary y-axis and a secondary y-axis. The limiting values are different for both axes. I want to keep the y-ticks on both axes such that they will look parallel to each other i.e. the starting tick 0 will be at the same location on both primary and secondary axes. Also, I want to change the color of left and right spine for each plot, but using ax.spines['left'].set_color('red')
is not working. The Plot Outline still remains black.
dataframes = [df1, df2, df3]
fig, axs = plt.subplots(1, 3, figsize=(16,4))
axs = axs.flatten()
primary_ticks_locations = [] # to store the locations of primary y-axis ticks
secondary_ticks_locations = [] # to store the locations of secondary y-axis ticks
for idx, (df, ax) in enumerate(zip(dataframes, axs)):
# Plot Data-A on Primary y-axis
primary_plot = ax.errorbar(df.index, df[df.columns[0]],
yerr=df[df.columns[1]], label='A', color='firebrick',capsize =5.5,
linewidth=2.0, marker='o', ms=5.0, mew=1.5, elinewidth=1.0, ls='solid')
ax.spines['left'].set_color('red') # Not working
ax.spines['right'].set_color('blue') # Not working
ax.set_ylim(-300, 4001) ## Set the y-limit for A-Data
# Collect primary y-axis tick locations
primary_ticks_locations.append(ax.yaxis.get_ticklocs())
## Set the x-axis label
ax.set_xlabel('saturation Level', fontsize=12, fontweight='bold')
## Create a secondary y-axis to plot AF
ax1 = ax.twinx()
## Plot B-data on the secondary y-axis
af_plot = ax1.errorbar(df.index, df[df.columns[2]],
yerr=df[df.columns[3]], label='B', color= 'royalblue',capsize =5.5,
linewidth=2.0, marker='D', ms=5.0, mew=1.5, elinewidth=1.0, ls='dashed')
ax1.set_ylim(-0.06, 1.01) ## Set the secondary y-axis limit
# Collect secondary y-axis tick locations
secondary_ticks_locations.append(ax1.yaxis.get_ticklocs())
# Customize the Primary y-axis ticks
ax.tick_params(axis='y',which = 'major', colors='firebrick')
# Customize the Secondary y-axis ticks
ax1.tick_params(axis='y', which = 'major', colors='royalblue')
# Customize the x-ticks
ax.tick_params(axis='x',which = 'major', colors='black')
plt.show()
primary_ticks_locations
shows: [array([-500., 0., 500., 1000., 1500., 2000., 2500., 3000., 3500.,4000., 4500.])
for each iteration.
secondary_ticks_locations
shows: [array([-0.2, 0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2])
for each iteration.
I don't understand how to make the number and location of the ticks on both axes the same and parallel. I also don't understand why ax.spines['left'].set_color('red')
is not producing the desired result.
This post explains how to change axis color: https://stackoverflow.com/a/12059429/23322818
To align the zero values, you could calculate the data range in each iteration of the for loop and manually set both axis to that range. If the two axis have different ranges, you can align the locations of the zero by aligning the relative position of zero along the two axis:
import numpy as np
import matplotlib.pyplot as plt
# Create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = t**2 - 50 + 20
data2 = np.sin(2 * np.pi * t) + 0.4
fig, ax1 = plt.subplots()
ax1.set_xlabel('time (s)')
# plot first line
ax1.plot(t, data1, 'red')
# format first axis
ax1.set_ylabel('exp', color='red')
ax1.spines['left'].set_color('red')
ax1.spines['right'].set_visible(False)
ax1.spines['left'].set_linewidth(3)
ax1.set_ylim(-30, 70)
# plot second line
ax2 = ax1.twinx()
ax2.plot(t, data2, 'blue')
# format second axis
ax2.set_ylabel('sin', color='blue')
ax2.yaxis.tick_right()
ax2.yaxis.set_label_position("right")
ax2.spines['right'].set_color('blue')
ax2.spines['left'].set_visible(False)
ax2.spines['right'].set_linewidth(4)
ax2.set_ylim(-.6, 1.4)
plt.show()