Python Forum
How to avoid the extra set of y-axis labels?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to avoid the extra set of y-axis labels?
#1
This programs works fine:

import matplotlib.pyplot as plt

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots(2,1)
axs[0].set_ylabel('Spread Price')
#axs[0].twinx().set_ylabel('SPX Price') #why does this add 0.0 to 1.0 axis labels AND overlap text?xs[0].plot(sample_df['Spread_Price'],color='red')
axs[0].twinx().plot(sample_df['SPX']) #twinx will always be the R axis.
axs[1].twinx().plot(sample_df['Spread_Price']) #need .twinx() as an attribute, and .plot is a method of that.
axs[1].plot(sample_df['SPX'],color='red')
#axs[0].twinx().set_yticklabels([])
plt.tight_layout()
plt.show()
The only problem is I don't have a secondary axis label.

If I uncomment L7, I get the secondary axis label ALONG WITH overlapping, y-axis labels from 0.0 to 1.0. What causes that and how do I remove those?

Thanks!
Reply
#2
twinx() creates a new axis. Your code creates two many new axis because you call twinx() multiple times. You should do something like this:
y2 = axs[0].twinx()
y2.set_ylabel('SPX Price')
I like the "Plots with different scales" example shown here

https://matplotlib.org/stable/api/_as_ge...twinx.html
Mark17 likes this post
Reply
#3
Thanks deanhystad! This works perfectly:

import matplotlib.pyplot as plt

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots(2,1)
twin0 = axs[0].twinx()
twin1 = axs[1].twinx()
axs[0].plot(sample_df['Spread_Price'], color='r')
axs[0].set_ylabel('Spread Price')
twin0.set_ylabel('SPX Price') 
twin0.plot(sample_df['SPX']) 
twin1.plot(sample_df['Spread_Price']) 
axs[1].plot(sample_df['SPX'],color='red')
plt.tight_layout()
plt.show()
I don't understand exactly how this solves the problem. Is twinx() not being called when done this way? It looks like it is---just through a substitution rather than directly?
Reply
#4
I also thought it might be the ax[0].set_ylabel() line in particular, but these two versions both generate that third, overlapping axis:

import matplotlib.pyplot as plt

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots()
twin0 = axs.twinx()
axs.set_ylabel('Spread Price')
axs.twinx().set_ylabel('SPX Price')  
axs.plot(sample_df['Spread_Price'],color='red')
twin0.plot(sample_df['SPX'])  #twin0 in this line
plt.show()
import matplotlib.pyplot as plt

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots()
twin0 = axs.twinx()
axs.set_ylabel('Spread Price')
twin0.set_ylabel('SPX Price')  #twin0 in this line
axs.plot(sample_df['Spread_Price'],color='red')
axs.twinx().plot(sample_df['SPX']) 
plt.show()
Reply
#5
twinx() is a function that creates an additional axis. Each time you call it it makes a new axis. In the working code twinx() is called once, to create one additional axis. You called twinx() multiple times on the same plot. This poor plot has 3 y axis
axs[0].twinx().set_ylabel('SPX Price') # This creates a new axis (#2)
axs[0].plot(sample_df['Spread_Price'],color='red')
axs[0].twinx().plot(sample_df['SPX']) # This creates an additional axis (#3), not the same as above
Reply
#6
(May-16-2022, 08:15 PM)deanhystad Wrote: twinx() is a function that creates an additional axis. Each time you call it it makes a new axis. In the working code twinx() is called once, to create one additional axis. You called twinx() multiple times on the same plot. This poor plot has 3 y axis
axs[0].twinx().set_ylabel('SPX Price') # This creates a new axis (#2)
axs[0].plot(sample_df['Spread_Price'],color='red')
axs[0].twinx().plot(sample_df['SPX']) # This creates an additional axis (#3), not the same as above

I still don't understand. Isn't a third axis being added to each of these subplots, too? Yet it works perfectly.

import matplotlib.pyplot as plt

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots(2,1)
twin0 = axs[0].twinx()
twin1 = axs[1].twinx()
axs[0].set_ylabel('Spread Price')
twin0.set_ylabel('SPX Price') # This creates a new axis in subplot 0 (#2)
axs[0].plot(sample_df['Spread_Price'],color='red')
twin0.plot(sample_df['SPX']) # This creates an additional axis in subplot 0 (#3), not the same as above
twin1.plot(sample_df['Spread_Price']) # This creates a new axis in subplot 1 (#2)
axs[1].plot(sample_df['SPX'],color='red')
axs[1].set_ylabel('SPX Price')
twin1.set_ylabel('Spread Price') # This creates an additional axis in subplot 1 (#3), not the same as above
plt.tight_layout()
plt.show()
Reply
#7
This creates two subplots. It returns a figure and an axes array.
fig, axs = plt.subplots(2,1)
axs[0] are the axes for the first subplot. axs[1] are the axes for the second subplot.

This is creating ONE additional y axis for each of your subplots.
twin0 = axs[0].twinx()   # Calling twinx() once for axs[0] creates 2nd y axis for first subplot
twin1 = axs[1].twinx()  # calling twinx() once for axs[1] creates 2nd y axis for second subplot
Each of your subplots now has 2 y axes

What you did in your initial post was treat twinx() like it returned a 2nd y axis. It does not. twinx() creates a new y axis. If you call twinx() ten times it will create 10 new y axes.

This is creating TWO additional y axes for one of your subplots.
axs[0].twinx().set_ylabel('SPX Price') # This creates a new axis (#2 y axis for the first subplot)
axs[0].plot(sample_df['Spread_Price'],color='red')
axs[0].twinx().plot(sample_df['SPX']) # This also creates a new y axis (#3 y axis for the first subplot)
For proof you could rewrite your original code like this.
import matplotlib.pyplot as plt
import pandas as pd

sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots(2,1)
axs[0].set_ylabel('Spread Price')

a = axs[0].twinx()
a.set_ylabel('SPX Price')

b = axs[0].twinx()
b.twinx().plot(sample_df['SPX'])

axs[1].twinx().plot(sample_df['Spread_Price'])
axs[1].plot(sample_df['SPX'],color='red')

c = axs[0].twinx()
c.twinx().set_yticklabels([])
print("These are all different axes", id(a), id(b), id(c))

plt.tight_layout()
plt.show()
Reply
#8
I think we're missing the source of my confusion.

(May-17-2022, 03:28 PM)deanhystad Wrote: What you did in your initial post was treat twinx() like it returned a 2nd y axis. It does not. twinx() creates a new y axis. If you call twinx() ten times it will create 10 new y axes.

That makes sense, and I did not understand this initially. I think what I don't understand is what does and does not "call twinx()":

import matplotlib.pyplot as plt
 
sample_data = [[3000,18], [3200,17], [3500,16], [4000,12]]
sample_df = pd.DataFrame(sample_data, columns = ['SPX', 'Spread_Price'])
fig, axs = plt.subplots(2,1)
twin0 = axs[0].twinx() #this calls twinx() for subplot 0
twin1 = axs[1].twinx() #this calls twinx() for subplot 1
axs[0].set_ylabel('Spread Price')
twin0.set_ylabel('SPX Price') #is this not calling twinx() for subplot 0 as well?  
axs[0].plot(sample_df['Spread_Price'],color='red')
twin0.plot(sample_df['SPX']) #is this not calling twinx() for subplot 0 as well?
twin1.plot(sample_df['Spread_Price']) #is this not calling twinx() for subplot 1 as well?
axs[1].plot(sample_df['SPX'],color='red')
axs[1].set_ylabel('SPX Price')
twin1.set_ylabel('Spread Price') #is this not calling twinx() for subplot 1 as well?
plt.tight_layout()
plt.show()
A few posts ago, I mentioned that to me this seems like [algebraic] substitution. Via substitution, twin0.plot = axs[0].twinx().plot. The right side is calling twinx() so why isn't the left also calling twinx()?
Reply
#9
If you have a function or method, like twinx, it gets called each time the function/method name is followed by (). The only time this is not true (that I can think of) is when making a lambda expression. When you see "name()", you are seeing a function/method call.

Python is not algebra. If this was true we would be screwed.
twin0 = axs[0].twinx()
twin0.plot == axs[0].twinx().plot
This would either mean that:
A) Functions always return the same value. Makes function not very useful.
B) Any object returned by a function calls the function each time the variable value is accessed. This makes variables rather useless (why not just have functions and no variables). Makes Python really slow. And doesn't deliver the results we want anyway (reusing a VALUE returned by a function instead of generating a new VALUE).

twin0 is an axis. It will always be the same axis (value) each time it is evaluated until you assign a new value. twinx() is a function call that returns a new axis. twinx() will create a new axis each time it is evaluated. This is just like "x = randint(1, 10)". x will be a randomly chosen value, lets say 7. If I print(x) it will print 7. If I assign "y = x + 3", y == 10. This is not true for randint(1, 10). If I "print(randint(1, 10)) I do not know what value will be printed. If I assign "y = randint(1, 10) + 3" all I know is that y is in the range 4 to 13.
Mark17 likes this post
Reply
#10
(May-17-2022, 04:21 PM)deanhystad Wrote: If you have a function or method, like twinx, it gets called each time the function/method name is followed by (). The only time this is not true (that I can think of) is when making a lambda expression. When you see "name()", you are seeing a function/method call.
...
twin0 is an axis. It will always be the same axis (value) each time it is evaluated until you assign a new value. twinx() is a function call that returns a new axis. twinx() will create a new axis each time it is evaluated.

Got it. Thanks so much!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How can histogram bins be separated and reduce number of labels printed on x-axis? cadena 1 850 Sep-07-2022, 09:47 AM
Last Post: Larz60+
  Floor division problem with plotting x-axis tick labels Mark17 5 2,047 Apr-03-2022, 01:48 PM
Last Post: Mark17
  x-axis labels with Matplotlib Mark17 8 2,123 Mar-23-2022, 06:10 PM
Last Post: Mark17
  Sample labels from excel file in order to put them on x-axis and y-axis of a plot hobbyist 11 4,232 Sep-14-2021, 08:29 AM
Last Post: hobbyist
  How to preserve x-axis labels despite deleted subplot? Mark17 1 1,888 Dec-23-2020, 09:02 PM
Last Post: Mark17
  Difference Between Figure Axis and Sub Plot Axis in MatplotLib JoeDainton123 2 2,426 Aug-21-2020, 10:17 PM
Last Post: JoeDainton123
  An Extra 'None' leoahum 5 3,821 Oct-18-2018, 08:20 PM
Last Post: volcano63

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020