I am working with a package that produces only a matplotlib.Axes object, but it produces exactly what I want for that particular figure.
It would be highly advantageous, however, to take that object and place it directly into a larger array of existing subplots. Something like the following:
fig, ax = plt.subplots(2, 2)
ax[0,0].plot(...stuff...)
ax[0,1].plot(...stuff...)
ax[1,0].plot(...stuff...)
foo = plot_likert.plot_likert(...stuff...); # <----- returns Axes object
ax[1,1] = foo # <----- transplant Axes object
fig.show(()
Obviously, it's not that simple. What happens (in jupyter, anyway) is that ax[1,1] shows up blank, and foo shows up as its own entity, nicely formatted.
Is there a way to do what I'm looking for?
Related
I was learning how to make graphs with python pandas. But I couldn't understand how this code works.
fig , ax = plt.subplots( ) ax = tips[['total_bill','tip']].plot.hist(alpha=0.5, bins=20, ax=ax)
I couldn't understand why the code words only when there is fig infront of ax.
Also I have no idea what 'ax=ax' means.
I found everywhere but I couldn't find the answer...
Pandas is using the library matplotlib to do the plotting. Try to read up a bit about how matploltib works, it will help you understand this code a bit.
Generally, plotting with matplotlib involves a figure and one or more axes. A figure can be thought of as a frame where multiple plots can be created inside. Each plot consists of an axes object which contains your x- and y-axis and so on.
With the command plt.subplots(), you create in a single function a figure object and one or more axes objects. If you pass no parameters to the function, just a single axes object will get created that is placed on the figure object. The figure and axes are returned as a tuple by the function in the form of (figure, axes). You are unpacking that tuple with the first line into the variable fig and ax.
Then, when you call the plotting function on your pandas data, you tell the function on which axes object to do the plotting. This is what the parameter ax means in that function. So you are telling the function to use your axes object that your variable ax is assigned to by setting the parameter ax to ax (ax = ax).
Doing ax = tips[['total_bill','tip']].plot... is redundant. The plotting function returns the axes object on which the plotting was performed by pandas. However, you are just overwriting your already existing axes with the returned axes, which in this case are the same object. This would only be needed if you don't pass the ax parameter to the plotting function, in which case pandas would create a brandnew figure and axes object for you and return the axes object in case you want to do any further tweaks to it.
I am using the function described here to get some diagnostics on multiple linear regressions.
The last code line reads # Fig and ax can be used to modify axes or plot properties after the fact.
My code:
cls = LRD(lm6_fit)
f,ax = cls();
Now, I have tried so many different ways to change the size of the figure but nothing worked...
if I run f? I some information about f, such as:
Type: Figure
String form: Figure(1000x1000)
Attributes
----------
patch
The `.Rectangle` instance representing the figure background patch.
suppressComposite
For multiple images, the figure will make composite images
depending on the renderer option_image_nocomposite function. If
*suppressComposite* is a boolean, this will override the renderer.
Init docstring:
Parameters
----------
figsize : 2-tuple of floats, default: :rc:`figure.figsize`
Figure dimension ``(width, height)`` in inches.
But I'm not sure how to modify the parameter figsize existing in f. I tried f.set_size_inches(K,L), for different values of K and L, but nothing changes.
I am calling sns.displot to get a FacetGrid
g = sns.displot(
data=df_all,
x='a_number',
hue='a_condition',
row='a_factor',
col='another_factor',
stat="density",
common_norm=False,
element='step',
palette=palette,
)
Similar to this question, I want to place the automatically-generated legend on one of the axes, instead of outside them as a figure-level legend:
How to put the legend on first subplot of seaborn.FacetGrid?
Just calling g.fig.axes[row][col].legend() does not work:
No handles with labels found to put in legend.
So I should generate the handles and labels?
I looked at how Grid.add_legend does this and it seems to be some magic that would require me knowing a lot more about how the class works to reproduce it (maybe I am wrong). There's also no _legend_data I can use to dynamically recreate the legend in the same way that the Grid.add_legend method does.
>>> g._legend_data
{}
The "easy" (lazy?) way would be if I could somehow copy the legend instance, add that copy to the axes I want, and then call g.fig._legend.remove() (unless anyone has any better ideas)
I can't figure out how to copy the legend and then assign it to a specific Axes.
It dawned on me I could just call g.legend.set_bbox_to_anchor() as a workaround.
In this case the legend is still figure-level but it lets me get it where I want it.
edit:
#mwaskom replied with a link to this comment on a GitHub issue, that has a code snippet that does what I had in mind:
https://github.com/mwaskom/seaborn/issues/2280#issuecomment-692350136
for my purposes I tweaked it like so
def move_legend(g, ax, new_loc, **kws):
old_legend = g.legend
handles = old_legend.legendHandles
labels = [t.get_text() for t in old_legend.get_texts()]
title = old_legend.get_title().get_text()
ax.legend(handles, labels, loc=new_loc, title=title, **kws)
move_legend(g, g.fig.axes[-2], "upper right")
g.legend.remove()
relevant discussion of what's going on under the hood is on that issue
One step in an application I'm writing creates plots to visualize various analyses for users. The methods that create these plots can be called individually, so their outputs are individual fig and ax objects.
One such method basically looks like this:
def make_a_plot(self):
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = self.x
y = self.y
ax.plot(x,y)
return fig, ax
So, if I call this method several times on different objects created by my class, I get fig1, fig2, ax1, ax2.
In another part of the program, I would like to be able to call this method a few times and then display all figures created together in one composite figure. Creating a new figure and adding ax1 and ax2 as separate subplots doesn't seem to work.
I also tried a for loop that gets ax1.lines[i].get_xdata() and ax1.lines[i].get_ydata() and creates new plots from them. But, I can't find a way to access other elements of the figure like vlines and fill_between values. So, that method got me about 50% of the way to the end before I found a wall.
How can I do this? I will gladly erect a shrine on a mountaintop somewhere of anyone who can help me solve this problem :)
I'm going through a data visualisation in python course to help with my lab reports and I cant seem to understand the purpose of the second line in this example of creating a scatter plot:
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.scatter([1,2,3,4,5],[1,2,3,4,5])
ax.set_xlabel('X')
ax.set_ylabel('Y')
plt.show()
Can someone explain what that first line is doing here.
I have only started using python and I haven't seen this sort of syntax before(fig,ax = plt.subplots()). I tried to test if it was a way to assign 2 variables to the same thing by writing x,y=1, I ended up getting an error "int object is not iterable".
Another thing I dont understand is where is fig being used anywhere in the body of code? My current understanding is that the top line defined what fig and ax are, I can see that ax is used in the body of the code to define the scatter plot, but where is fig used? I tried to delete it and run the code, but I got this error:
'tuple' object has no attribute 'scatter'
If someone could please explain the above misconceptions.
As per the official docs, subplots creates a figure and a set of subplots. Specifically,
Returns:
fig : Figure
ax : axes.Axes object or array of Axes objects. ax can be either a single Axes object or an array of Axes objects if more than one subplot was created. The dimensions of the resulting array can be controlled with the squeeze keyword, see above.
Now when you do
fig, ax = plt.subplots()
the figure object is assigned to the variable fig and the axis object is assigned to the variable ax.
The fig will then give you access to the attributes on a figure-level, for instance, the figure title. The ax will give you access to the attributes on individual subplot level, such as the legends, axis-labels, ticks, of each individual subplot. It will be as array of Axes objects in case you have more than one subplot.
I tried to test if it was a way to assign 2 variables to the same thing by writing x,y=1, I ended up getting an error "int object is not iterable".
You are almost right. That is syntax to assign multiple variables at the same time, but what you are missing is that plt.subplots() returns a tuple - of two values paired together.
If you want to better understand it you can run:
a, b = (1, 4)
or
a,b = 1, 4
(it's the same as far as python is concerns, it packs/unpacks values to a tuple if multiple values are used or returned)
I tried to delete it and run the code, but I got this error:
'tuple' object has no attribute 'scatter'
This is also related to why you got this error. The figure is indeed not in use in your code snippet, but you need it for python to understand you want to use part of the tuple and not the tuple itself.
For example: a=(1,2) will result in a holding a tuple, but in a, b = 1, 2 each of the created variables will hold an integer.
In your case, the axis object has a method scatter, which the tuple object does not have, hence your error.