0

I am trying to plot two-axis plots in matplotlib. The two y axis in my plot use different starting point in the graph, How can I correct it so that both the y axis plots use the same axis points.

The code I use to plot is

fig = plt.figure(figsize=(30, 20))
ax = fig.add_subplot()
ax1 =ax.twinx()
#ax.grid(True,axis='both')
#ax.set(xlabel="Voltage", ylabel="Current", title="IV Curve") 
ax.set_xlabel("Voltage [V]",fontsize = 20)
ax1.set_xlabel("Voltage [V]",fontsize = 20)
ax.set_ylabel("Current [I]",fontsize = 20)
ax1.set_ylabel("Power [W]",fontsize = 20)
ax1.spines['right'].set_color('red')
ax.spines['left'].set_color('red')
ax.get_shared_x_axes().join(ax, ax1)
#ax.set_title("IV/PV Curve Plot",fontweight ='bold', fontsize = 30, color='blue')
ax1.tick_params(axis='both', which='both', labelsize=20)
plt.ylim (0,10) #adjust the current limits
plt.xlim (0,70) #adjust the voltage limits
ax.tick_params(axis='both', which='both', labelsize=20)
plt.ylim (0,400) #adjust the power limits
plt.xlim (0,70) #adjust the voltage limits

ax.plot('Voltage', 'Current', data=df, linewidth=4, label='IV curve')
ax1.plot('Voltage', 'Power', data=df, linewidth=4, color='r', label ='PV Curve')
ax.legend( loc='upper right',fontsize=20)
ax1.legend(loc='lower right',fontsize=20)
#pmax and Vmax

Pmax = df["Power"].max()
maxrow = df[df['Power']==Pmax]
Voltage = maxrow['Voltage'].iloc[0]
Current = maxrow['Current'].iloc[0]
xmax1 =(Voltage/70)
xmax2 =(Current/10)
ax.axhline(y=Current, xmin=0, xmax =xmax1,linewidth=4, color ='g',linestyle='--',)
ax.axvline(x=Voltage, ymin=0, ymax =xmax2, linewidth=4, color='g', linestyle='--')

#img = image.imread("/home/hebin/Desktop/PV/Mitsui/Flasher/Mitsui Logo.png")
#plt.figimage(img, 1380, 1150, alpha=1)
plt.margins(0)
plt.tight_layout()
#plt.savefig('/home/hebin/Desktop/PV/Mitsui/Flasher/IVC/IV.png')

and my output is like this enter image description here

In the image you can see the red line and the blue line starts at point zero but at different starting points. I want to correct it and make it start from the same point.

hebin manuel
  • 47
  • 1
  • 7
  • Some data would be nice for testing. – Grayrigel Sep 27 '20 at 10:29
  • 2
    You need to change `plt.ylim` to `ax1.set_ylim` etc.. Also, you need to wait with changing the limits until the last command that creates new elements on that ax. Most commands that add new elements also change the limits. Note that `plt.margins()` also change the limits, so you need to choose between either `ax1.set_ylim` or `ax1.margins()`. Better not use the `plt....` commands that operate on subplots when you have multiple axes. See e.g. https://stackoverflow.com/questions/37970424/what-is-the-difference-between-drawing-plots-using-plot-axes-or-figure-in-matpl – JohanC Sep 27 '20 at 10:52

1 Answers1

0

To aling zero in a twin axes, define the following function:

def alignZero(ax1, ax2):
    y1Min, y1Max = ax1.get_ylim()
    y2Min, y2Max = ax2.get_ylim()
    ratio1 = -y1Min / (y1Max - y1Min)
    ratio2 = -y2Min / (y2Max - y2Min)
    if ratio2 < ratio1:
        y2newMin = y1Min * y2Max / y1Max
        ax2.set_ylim(y2newMin, y2Max)
    elif ratio2 > ratio1:
        y2newMax = y2Min * y1Max / y1Min
        ax2.set_ylim(y2Min, y2newMax)

Then check how it works:

fig = plt.figure()
ax1 = fig.add_subplot()
ax2 = ax1.twinx()
ax1.bar(range(6), (2, -2, 1, 0, 0, 0))
ax2.plot(range(6), (0, 2, 8, -12, 0, 0))
ax1.axhline(0, color='red', linestyle='--', linewidth=1)
alignZero(ax1, ax2)
plt.show()

The generated picture is:

enter image description here

In the above example there was a need to set higher max value for ax2 (y2newMax).

Make the second test changing -12 in ax2.plot(...) to e.g. -4. This time the min value in ax2 (y2newMin) was lowered.

And to see how would the result look like without the above alignment, make one more test, with commented out invocation of alignZero (zeroes will be now at different levels).

Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41