I am using the basic axis.annotate(str(i)) function to show values along the points of my graph. The problem is quite quickly they get to bunched together. So I have two questions: How can I remove an annotation? And how can I make one smaller (font size)?
Here is the reference to the annotation method:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.annotate
I have done my research and surprisingly found nothing. Cheers.
axis.annotate(str(i)) returns an axes Annotation object. You need to assign a variable to it and then you manipulate it however you want.
fig, ax = plt.subplots(1,1)
ax.plot(range(5))
text = ax.annotate(xy = (2,2), s='asdf')
# use any set_ function to change all the properties
text.set_fontsize(20)
Related
Practicing on visualization as a Python newbie I have encountered this conceptual issue that got me thinking,
Infact I managed to change the price format on the y axis of a boxplot , from scientific notation to something more clear. Here the outputs before and after the formatting of the y axis
before
after
boxy=sns.boxplot(x="waterfront", y="price", data=df)
# my experiments success
from matplotlib.ticker import FuncFormatter
f = lambda x, pos: f'{x:.0f}'
boxy.yaxis.set_major_formatter(FuncFormatter(f))
the problem is that I realized that the attribute yaxis should refer to an AXIS object, meanwhile here what i call 'boxy' is an AXES object (at least from the seaborn documentation)
Can anyone explain it?
You're right saying that seaborn boxplot returns a matplotlib Axes object. And referring to this answer, we see Axes and Axis objects are different.
Code inspection isn't needed... but under the hood, seaborn uses matplotlib, it is noted in the GitHub here for boxplots.
when you call sns.boxplot part of drawing your plot creates Axis objects... which are objects of the matplotlib.axis module.
The y axis is in fact the first part of boxy.yaxis.set_major_formatter(FuncFormatter(f))
it is accessed with boxy.yaxis. On which you are calling the function .set_major_formatter(FuncFormatter(f)).
To see this, yaxis = boxy.get_yaxis() will return the yaxis of the boxy axes object.
EDIT IN RESPONSE TO COMMENT:
Again you're correct in the comment that this is not documented from what I could find... but if we look in the matplotlib GitHub here, we see in the YAxis class declaration:
class YAxis(Axis):
__name__ = 'yaxis'
It is just 'YAxis' renamed. Classes will assume their name in the declarative line, unless you re-specify using __name__ which was done here!
It exists!!!
boxy's yaxis inherets the set_major_formatter method from its base class, the 'Axis' class. Just to confirm this hierarchy try looking with method resolution order:
print(type(boxy.get_yaxis()).__mro__)
Should display:
(<class 'matplotlib.axis.YAxis'>, <class 'matplotlib.axis.Axis'>, <class 'matplotlib.artist.Artist'>, <class 'object'>)
The code I am currently using has the following:
import matplotlib.pyplot as plt
fig = plt.figure(1)
My question is the following: What is the "1" for? I assume it is some kind of index, but the documentation does not have this parameter:
class matplotlib.figure.Figure(figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=0.0, frameon=None, subplotpars=None, tight_layout=None)
Am I missing something? I am pretty sure that I am not the first one to ask this, but neither search nor "Questions that may already have your answer" gave me an answer...
Am I supposed to increase this for the next figure I plot?
You would need to look at the documentation of the command you're using, not some other.
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None,...) has a num argument.
num : integer or string, optional, default: none
If not provided, a new figure will be created, and the figure number will be incremented. The figure objects holds this number in a number attribute. If num is provided, and a figure with this id already exists, make it active, and returns a reference to it. If this figure does not exists, create it and returns it. If num is a string, the window title will be set to this figure’s num.
You don't need to use this, successive calls of plt.figure() will create new figures automatically.
from datetime import datetime
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
data=pd.read_csv(r"C:\Users\champion\Desktop\ch02\spx.csv")
spx=data["SPX"]
spx.plot(**ax=ax**,style="k-")
I can't understand why "ax=ax" meaning in matplotlib.
From the documentation of plot():
DataFrame.plot(x=None, y=None, kind='line', ax=None, subplots=False,
sharex=None, sharey=False, layout=None, figsize=None, use_index=True,
title=None, grid=None, legend=True, style=None, logx=False,
logy=False, loglog=False, xticks=None, yticks=None, xlim=None,
ylim=None, rot=None, fontsize=None, colormap=None, table=False,
yerr=None, xerr=None, secondary_y=False, sort_columns=False, **kwds)
Parameters: ax : matplotlib axes object, default None
You can see that ax is a keyword argument here. It just happens that you also named your variable as ax and you are sending it as the value of that keyword argument to the function plot().
Ax is the keyword for the part of the overall figure in which a chart/plot is drawn. So, when you type "spx.plot(**ax=", you are declaring the values for that part of the figure. The reason you are saying "ax=ax" is, as Nahal rightly pointed out, because you defined a variable named "ax" on the third line of code and you are using that to say what the ax keyword should be.
Here's an article with some helpful visuals.
https://towardsdatascience.com/what-are-the-plt-and-ax-in-matplotlib-exactly-d2cf4bf164a9
The current thought of the previous explanations are true, but it's an argument for a Series.plot() method.
Importing this
data=pd.read_csv(r"C:\Users\champion\Desktop\ch02\spx.csv")
What you are getting is a DataFrame.
And then:
spx=data["SPX"]
The code above is giving you a Series back. So, we are dealing with a Series.plot() method - but there is the same argument dor DataFrame.plot().
First of all, it is important to understand that this plot() method is correlated but not the same as the plot() function from matplotlib.
When you create a figure with:
fig=plt.figure()
It creates something like a blank sheet, and you can't create a plotting in a blank sheet.
The next code creates a subplot where you can finally plot something.
ax=fig.add_subplot(1,1,1)
And now we are getting to the question.
spx.plot(ax=ax,style="k-")
This piece of code is calling the plot method for a Series, and inside this method there is an optional argument called 'ax'.
The description of this argument says that it is an object of plotting from matplotlib for this plotting you want to do. If nothing is specified in there, so it makes use of the active subplotting of matplotlib.
Long story short, in your example there is only one active subplotting, and it is the 'ax' that was created before, so you could run your code without 'ax=ax', with the same result.
But it will make sense in a context when you have more than one subplotting object, so you could specify in wich one you would like to plot the spx Series.
We could have created a second and a third subplot, like this:
ax1 = fig.add_subplot(2, 2, 2)
ax2 = fig.add_subplot(2, 2, 3)
In this case, if I want to plot that Series on the 'ax1', I could have passed that to the argument:
spx.plot(ax=ax1,style="k-")
And now it is plotting on the exact box I wanted in the figure.
I have a GUI built using PyQt4 where I use matplotlib (FigureCanvas) to plot several plots using multiple canvases (this is intentional rather than using subplots). for each canvas I use method:
self.canvas_xx.mpl_connect('scroll_event', self.on_mouse_scroll)
where xx represents the iteration of the canvas to get a signal to perform some action. I want to be able to reference the canvas by its name rather than using:
ylabel = event.inaxes.axes.get_ylabel().split(' ')[0]
where I use the longer method of referncing the ylabel name of each graph.
I looked under the event method using: dir(event) and there is a method called "canvas", but there is no apparent method to get the name of the canvas.
Any ideas?
I am not quite sure what you mean by name, but you can get a a reference to the canvas object via
event_canvas = event.inaxes.axes.figure.canvas
and canvas events are hashable, so you can use them as keys in a dict
other_thing = pre_populated_dict[event_canvas]
to keep track of what ever other data you want to about a given canvas in your code.
In python there is, in general, not a clean way to get the names of references to an object (it can be done, but you shouldn't).
I made a GUI with TKinter that reads a scope trace from a agilent scope. I want the x axis to update when I change time/div. To update the x and y data I use set_xdata and set_ydata. Is there a similar method for updating the x limits?
You need to understand a bit of the object hierarchy. You are calling set_xdata on a Line2D object, which is an Artist which is associated with an Axes object (which handles things like log vs linear, the x/y limits, axis label, tick location and labels) which is associated with a Figure object (which groups together a bunch of axes objects, deals with the window manager (for gui), ect) and a canvas object (which actually deals with translating all of the other objects to a picture on the screen).
If you are using Tkinter, I assume that you have an axes object, (that I will call ax).
ax = fig.subplot(111) # or where ever you want to get you `Axes` object from.
my_line = ax.plot(data_x, data_y)
# whole bunch of code
#
# more other code
# update your line object
my_line.set_xdata(new_x_data)
my_line.set_ydata(new_y_data)
# update the limits of the axes object that you line is drawn on.
ax.set_xlim([top, bottom])
ax.set_ylim([left, right])
so to update the data in the line, you need to update my_line, to update the axes limits, you need to update ax.
set_xlim doc and set_ylim doc
The pyplot.xlim() function changes the range of the x axis (of the current Axes).
The set_xticks() method of Axes sets the ticks. The current Axes can be obtained for instance with gca().