subplot using automatic resizing - python

looking for some "magic" command that make the maps of the subplots (2x2 in my case) well speared not too much but with the right spacing in order to be considered "quality plot" I found that i can set all using the option rect inside plt.tight_layout I spend time to find this parameters : plt.tight_layout(rect=(0.02,0.02,0.97,0.97))
Now the plot is fitting well the pdf image but the 2 plots of the top is to close to the 2 below look the picture without going out of bound on the top ? and how can obtain the plot title a bit more separate respect the figure ? hope in your hint !
EDIT ok .. if I use the command plt.title('...',y=1.1) this is taken just on the last plot (the axs[1,1]) while I'm write the command before all the subplot !

Sorry I don't have an answer for automatic resizing but since you asked for some hints, there is one possible solution:
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
What you need is wspace for horizontal spacing and hspace for horizontal spacing between the subplots. This gives you freedom to choose the desired spacing to make your plot a "quality plot". Hope it helps.
As to your second question about placing the title, you can use:
plt.title("Title here", y=1.25)
where y defines the position of your title in relative coordinates. y=1 would mean at the top x-axis and y=0.5 would mean in the centre of the plot. Since you have a title for each subplot, you can use the respective relative coordinates for each.

Related

How to adjust subplots borders in matplotlib automatically?

When plotting multiple plots using plt.subplots, most of the time the spacing between subplots is not ideal so the the xtick labels of the top plot would overlap with the title of the bottom plots. There is a way to fix this manually by calling say plt.subplots_adjust(hspace=0.5) and changing the parameters interactively to obtain a decent looking plot. Is there a way to calculate the subplot_adjust parameter automatically? Meaning finding the minimum hspace and wspace so that there is not overlap between texts of the plots.
You can use tight_layout https://matplotlib.org/stable/tutorials/intermediate/tight_layout_guide.html or constrained_layout https://matplotlib.org/stable/tutorials/intermediate/constrainedlayout_guide.html
I'm pretty certain that the closest your going to find to an inbuilt calculation method is:
plt.tight_layout()
or
figure.Figure.tight_layout() #if you are using the object version of the code

How to ajust the location of the labels in legend?

I plotted a figure as the attached picture.
There are 3 labels in the legend.
As you can see, the label on the second row is quite long, so I'd like to set the right of “BS” label align with the end of "Farinotti et al. (2019)" label.
How should I do this?
Basically, you're thinking "these labels form a 2x2 grid, and I want the bottom row to span 2 columns"?
To be honest, I don't think that's necessary; to my eyes your legend looks fine. This won't save as much white space, but you could save some by just swapping the positions of "BS" and "Farinotti". Saving more white space than that would be inconsequential here. You can have a look at this other answer for tips on how to flip the label positions:
Matplotlib legend, add items across columns instead of down
But if you want to go down the path of creating column-spanning labels anyway, for a more extreme case or out of curiosity, what you want to do is define your own legend handler. Required reading:
https://matplotlib.org/1.3.1/users/legend_guide.html
https://matplotlib.org/3.1.0/api/legend_handler_api.html
Or here's a somewhat hacky answer I found that combines 2 legends into 1, which should give you the effect that you're looking for.
pyplot: change ncols within a legend

How to add box plots on top of scatter plot

I want to plot boxplots on top of the scattered points like this.
I know I have to bin the data into intervals first but I couldn't find the function that does all of this. Sample x and y data are saved here as .npy.
I would look into using matplotlib. Boxes can be drawn as such:
https://matplotlib.org/gallery/pyplots/boxplot_demo_pyplot.html?highlight=boxplot
and scatter plots can also be drawn as such: https://matplotlib.org/gallery/lines_bars_and_markers/scatter_demo2.html?highlight=scatter
There is a search functionality on their site, along with plenty of documentation on how to utilize their library.
As for your specific question, you can specify zorder when drawing many of the things in matplotlib, and you could use that to define your boxplots to be on top. I believe if no zorder is defined that it draws items in the order they are encountered in your program (so you could draw scatter plots and then box plots and they should appear correctly as in your diagram above!

Need to add a "legend" to an arrow/contour plot

I am plotting some scalar data as a contour plot with matplotlib.contourf. On top of it, I am plotting some vector data with matplotlib.arrow. The basic plot has come along OK, but now I need to put a box on the plot with a default-size arrow plus the data value to which it corresponds, so the viewer will know what kind of scale he is looking at. For instance, I need a box with a horizontal arrow of some length and, below that, some text like "10 cm/sec".
First, if anyone can give me a simple approach to this, I would be grateful.
Second, the approach I have tried is to do the contour plot, then plot the arrows, then add a rectangle to the plot like so:
rect=pl.Rectangle((300,70),15,15,fc='white')
pl.gca().add_patch(rect)
and then, finally, put my scale arrow and text on top of this rectangle.
This isn't working because the rectangle patch covers up the contour, but it doesn't cover up the arrows in the plot. Is there a way to move the patch completely "to the front" of everything else?
Got it. Using pylab.quiver and pylab.quiverkey functions. quiver produces a nice vector field with just a few lines of code, and quiverkey makes it easy to produce a scaling vector with text. And, for some reason, the arrows plotted with quiver are indeed covered by my rectangle, so it is easy to make the scaling arrow very visible. There are still some mysteries in all of this for me. If anyone wants to try to clear them up, would be much obliged. But I have a way now to do what I need in this instance.

On adjusting margins in matplotlib

I am trying to minimize margins around a 1X2 figure, a figure which are two stacked subplots. I searched a lot and came up with commands like:
self.figure.subplots_adjust(left=0.01, bottom=0.01, top=0.99, right=0.99)
Which leaves a large gap on top and between the subplots. Playing with these parameters, much less understanding them was tough (things like ValueError: bottom cannot be >= top)
My questions :
What is the command to completely minimize the margins?
What do these numbers mean, and what coordinate system does this follow (the non-standard percent thing and origin point of this coordinate system)? What are the special rules on top of this coordinate system?
Where is the exact point this command needs to be called? From experiment, I figured out it works after you create subplots. What if you need to call it repeatedly after you resize a window and need to resize the figure to fit inside?
What are the other methods of adjusting layouts, especially for a single subplot?
They're in figure coordinates: http://matplotlib.sourceforge.net/users/transforms_tutorial.html
To remove gaps between subplots, use the wspace and hspace keywords to subplots_adjust.
If you want to have things adjusted automatically, have a look at tight_layout
Gridspec: http://matplotlib.sourceforge.net/users/gridspec.html

Categories