How to move plot to the left of window in matplotlib - matplotlib

I have a plot with a very wide legend.
I've managed to move the legend out of the plot so that it doesn't cover it, but the legend is too wide for the window and not completely visible. This could be corrected if I knew how to move plot and legend towards the left where there is spare space.
This is what I mean:
What instruction would allow me to do this?
My current code:
f,ax=plt.subplots(1)
f.set_size_inches(14,10.5)
...
plt.legend(bbox_to_anchor=(1,1), loc="upper left")
plt.show()
Thank you

You can try adjusting the margins. The line to do that is f.subplots_adjust(left=0.05, bottom=0.07, right=0.95, top=0.95, wspace=0, hspace=0). These values can be controlled from the button to the left of the save button on the bottom toolbar. So, you can try playing with those in the gui, then when you find a value you like or that works, enter them in the suggested line of code.
Then you code should look like .
f,ax=plt.subplots(1)
f.set_size_inches(14,10.5)
...
plt.legend(bbox_to_anchor=(1,1), loc="upper left")
f.subplots_adjust(left=0.05, bottom=0.07, right=0.95, top=0.95, wspace=0, hspace=0)
plt.show()

Related

How do I stretch our the horizontal axis of a matplotlib pyplot?

I'm creating a colour map which has 64 horizontal data points and 3072 vertical. When I plot it, the scaling on both axes is the same and so the horizontal axis is super squished and tiny, and I can't get any information from it. I've tried changing the figsize parameter but nothing changes the actual plot, only the image that contains it. Any ideas on how to change my plot so that the actual length of the axes are the same? Below is my plotting code:
def plot_plot(self, data, title="Pixel Plot"):
pixel_plot = plt.imshow(data)
plt.title(title)
plt.colorbar(pixel_plot)
plt.show(pixel_plot)
thanks in advance!
I think you want the aspect option in plt.imshow().
So something like plt.imshow(data, aspect=0.1) or plt.imshow(data, aspect='equal')
See this solution: https://stackoverflow.com/a/13390798/12133280

How to remove the whitespace between the tip of the arrow of a FancyArrowPatch and the target points?

When doing an image which puts lots of focus on some arrows, I noticed that the arrows didn't reach the full length between the specified points.
For example:
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots()
fig.set_size_inches(5, 5)
w = 0.001
h = 1000
ax.set_xlim(0, w)
ax.set_ylim(0, h)
ax.add_artist(mpl.patches.FancyArrowPatch(
(w*1/3, h*0.0),
(w*1/3, h*1.0),
edgecolor='black',
facecolor='red',
arrowstyle=mpl.patches.ArrowStyle.CurveFilledAB(head_length=10, head_width=10)
))
ax.add_artist(mpl.patches.FancyArrowPatch(
(w*2/3, h*0.0),
(w*2/3, h*1.0),
edgecolor='black',
facecolor='red',
arrowstyle=mpl.patches.ArrowStyle.Simple(head_length=10, head_width=10, tail_width=1)
))
plt.savefig(
'main.svg',
format='svg',
bbox_inches='tight',
dpi=100,
)
produces:
and here is a screenshot of a browser zoom of the arrows showing that they don't touch the black line above:
How to make them touch exactly without that white space?
Tested on matplotlib==3.2.2.
Related questions:
Alter the width of an annotate arrow in matplotlib
Matplotlib - set pad between arrow and text in annotate function
shrinkA=0 and shrinkB=0
This is the first main direct reason why arrows don't touch.
Those values default to 2, presumably because arrows were originally mostly used in annotations where some space is desired.
If I set them to zero:
FancyArrowPatch(
shrinkA=0,
shrinkB=0,
then the arrows touch as shown at:
A is for the start, and B is for the end of the arrow.
The effect of linewidth
Another thing to keep in mind however is that the linewidth can also affect if the arrow touches something or not.
For example, if I add an exaggerated linewidth=10 to the original code:
FancyArrowPatch(
shrinkA=0,
shrinkB=0,
linewidth=10,
then the result is:
so we note how:
the tracing of the edges is always rounded, and therefore the arrows stop being pointy and become rounded with large line widths
Simple and CurveFilledAB have different drawing algorithms: the one for Simple makes the arrow overrun the target, and CurveFilledAB makes it under run
the linewidth above was so fat that it hid the red inner color
For the case of Simple, if you don't need a different border color, you can get back the pointy arrow with linewidth=0, and control the main arrow line width with tail_width.
This does not work for CurveFilledAB however: the drawing algorithm for that style is to use the border alone for the main arrow line, so I'm not sure how to separately control the main line width of a double headed arrow without getting the rounded corners, except for drawing two simple arrows which is uglier: matplotlib simple and two head arrows Seems like something that could be patched by adding a new SimpleAB class.
The result of:
FancyArrowPatch(
shrinkA=0,
shrinkB=0,
linewidth=0,
is:

How to get legend next to plot in Seaborn?

I am plotting a relplot with Seaborn, but getting the legend (and an empty axis plot) printed under the main plot.
Here is how it looks like (in 2 photos, as my screen isn't that big):
Here is the code I used:
fig, axes = plt.subplots(1, 1, figsize=(12, 5))
clean_df['tax_class_at_sale'] = clean_df['tax_class_at_sale'].apply(str)
sns.relplot(x="sale_price_millions", y='gross_sqft_thousands', hue="neighborhood", data=clean_df, ax=axes)
fig.suptitle('Sale Price by Neighborhood', position=(.5,1.05), fontsize=20)
fig.tight_layout()
fig.show()
Does someone has an idea how to fix that, so that the legend (maybe much smaller, but it's not a problem) is printed next to the plot, and the empty axis disappears?
Here is my dataset form (in 2 screenshot, to capture all columns. "sale_price_millions" is the target column)
Since you failed to provide a Minimal, Complete, and Verifiable example, no one can give you a final working answer because we can't reproduce your figure. Nevertheless, you can try specifying the location for placing the legend as following and see if it works as you want
sns.relplot(x="sale_price_millions", y='gross_sqft_thousands', hue="neighborhood", data=clean_df, ax=axes)
plt.legend(loc=(1.05, 0.5))

How to create a new plot which is already zoomed once in matplotlib?

I want to create a new plot which is already zoomed once. means that if I hit the home button it will return full view.
This is similar to using the box zoom button but programmatically.
something like this:
fig, axes = plt.subplots()
axes.plot(range(10)) # just some plot
axes.set_zoomed_xlim(3,7) #different from set_xlim because you can see the whole plot if you hit Home
Do you guys know something like this magic set_zoomed_xlim ?
Thanks

How do I set the resize-behaviour of subplots?

I'm working with several subplots in a window. Just after plotting it looks great, problem is when I rezise the windows manually. The subplots do not adapt correctly to the new size of the window. How can I fix that?
Window after plotting, looking great:
window after resizing it manually, looks bad:
EDIT:
A simply demo-Code:
from matplotlib.pyplot import *
figure(figsize=(24,6))
subplot(131)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
subplot(132)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
subplot(133)
ylabel("test")
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
tight_layout()
show()
As you see, the plot looks good after plotting it. But when you start to shrink the plot horizontally, the space between plot and plot gets smaller and smaller. And at the end, the ticklabels are on others plots, because there's no space for them. I need to know how to set that the entire plot gets smaller, leving space for the labels.
Maybe not exactly the answer of my question, but it solves my problem:
After creating the figure, you connect the resize-event to an eventhandler:
cid = fig.canvas.mpl_connect('resize_event', onresize)
def onresize(event):
plt.tight_layout()
As Wicket said, I'm just calling tight_layout() again and again, but automatically.