Title of figure between the subplots - python

When I make a figure with two subplots in the following way:
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
the title appears between the subplots:
plt.title('Title')
plt.show()
How can I have the title on the top of the figure instead?

What you are looking for is suptitle which places a centered title at the top of the figure.
Using plt.title (applies to the current axis which is ax2 in your case)
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
plt.title('Title')
Using plt.suptitle
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
plt.suptitle('Title')
As suggested by #ImportanceOfBeingErnest , you can also use ax1.set_title('Title') to put the title on the top because ax1 corresponds to the top sub figure in your case.

Related

Aligning colormap consistently with the plot

I am trying to align the matplotlib plot with its colorbar. However, when there is a tick on the top of the colormap, the figure itself shrinks a little bit:
Is there a way to equalize this distance (blue arrows) consistently?
For generating the plot, I am using following code:
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
ax.plot(...)
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes('right', '5%', pad='3%')
sm = plt.cm.ScalarMappable(cmap=plt.get_cmap('viridis'),
norm=mpl.colors.Normalize(vmin=0, vmax=60))
sm.set_array([])
fig.colorbar(sm, cax=cax)
plt.tight_layout()
plt.savefig('pic.png', dpi=500)

Combined Pie Chart and Bar Plot - Python Matplotlib [duplicate]

When I make a figure with two subplots in the following way:
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
the title appears between the subplots:
plt.title('Title')
plt.show()
How can I have the title on the top of the figure instead?
What you are looking for is suptitle which places a centered title at the top of the figure.
Using plt.title (applies to the current axis which is ax2 in your case)
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
plt.title('Title')
Using plt.suptitle
import matplotlib.pyplot as plt
fig=plt.figure(1)
(ax1,ax2) = fig.subplots(2,1, gridspec_kw={'height_ratios':[1,15]})
plt.suptitle('Title')
As suggested by #ImportanceOfBeingErnest , you can also use ax1.set_title('Title') to put the title on the top because ax1 corresponds to the top sub figure in your case.

How to force aspect ratio of subplot while keeping the width identical?

I'm trying to create a plot with two subplots. 1 column, 2 rows.
Similar to the image but without the subplot to the right
How can I enforce one subplot to be square and the other one to have the same width without being square?
I tried gridspec without success:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
fig = plt.figure(constrained_layout=True)
gs = GridSpec(nrows=4, ncols=3, height_ratios=[1, 1, 1, 1], figure=fig)
ax1 = fig.add_subplot(gs[:-1,:])
ax2 = fig.add_subplot(gs[-1,:])
I also tried setting the aspect ratio for both subplots resulting in different widths the subplots:
fig, axs = plt.subplots(2)
axs[0].set_aspect(1)
axs[1].set_aspect(2)
I also tried... but this fixes the x range of the subplots to the same value.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
F = plt.figure()
grid = ImageGrid(F, 111,
nrows_ncols=(2, 1),
axes_pad=0.1,
)
grid[1].set_aspect(.4)
Thanks for any suggestions...
One working solution I could come up with following the suggestions of ImportanceOfBeingErnest:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable
fig = plt.figure(figsize=(10,12))
axScatter = plt.subplot(111)
axScatter.set_aspect(1.)
divider = make_axes_locatable(axScatter)
axHistx = divider.append_axes("bottom", size=.8, pad=0.2)
Thank you!

Seaborn despine with two y-scales (twinx)

How can I keep seaborn.despine from putting both of my y-scales onto the left side of my plot?
The best I've come up with so far is:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("white")
fig, ax = plt.subplots()
ax.plot(np.random.rand(10))
ax2 =ax.twinx()
ax2.plot(100*np.random.rand(10))
sns.despine(ax=ax, right=True, left=True)
sns.despine(ax=ax2, left=True, right=False)
But any other combination will either not despine the y-axes or put the right axis onto the left.
Output of the above: (desired output has no spines, just numbers on left and right)
I guess that's what you want then.
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("white")
fig, ax = plt.subplots()
ax.plot(np.random.rand(10))
ax2 =ax.twinx()
ax2.plot(100*np.random.rand(10))
sns.despine(ax=ax, right=True, left=True)
sns.despine(ax=ax2, left=True, right=False)
ax2.spines['right'].set_color('white')

Positioning the colorbar

I have a matplotlib plot with a colorbar attached. I want to position the colorbar so that it is horizontal, and underneath my plot.
I have almost done this via the following:
plt.colorbar(orientation="horizontal",fraction=0.07,anchor=(1.0,0.0))
But the colorbar is still overlapping with the plot slightly (and the labels of the x axis). I want to move the colorbar further down, but I can't figure out how to do it.
using padding pad
In order to move the colorbar relative to the subplot, one may use the pad argument to fig.colorbar.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
fig, ax = plt.subplots(figsize=(4,4))
im = ax.imshow(np.random.rand(11,16))
ax.set_xlabel("x label")
fig.colorbar(im, orientation="horizontal", pad=0.2)
plt.show()
using an axes divider
One can use an instance of make_axes_locatable to divide the axes and create a new axes which is perfectly aligned to the image plot. Again, the pad argument would allow to set the space between the two axes.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np; np.random.seed(1)
fig, ax = plt.subplots(figsize=(4,4))
im = ax.imshow(np.random.rand(11,16))
ax.set_xlabel("x label")
divider = make_axes_locatable(ax)
cax = divider.new_vertical(size="5%", pad=0.7, pack_start=True)
fig.add_axes(cax)
fig.colorbar(im, cax=cax, orientation="horizontal")
plt.show()
using subplots
One can directly create two rows of subplots, one for the image and one for the colorbar. Then, setting the height_ratios as gridspec_kw={"height_ratios":[1, 0.05]} in the figure creation, makes one of the subplots much smaller in height than the other and this small subplot can host the colorbar.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
fig, (ax, cax) = plt.subplots(nrows=2,figsize=(4,4),
gridspec_kw={"height_ratios":[1, 0.05]})
im = ax.imshow(np.random.rand(11,16))
ax.set_xlabel("x label")
fig.colorbar(im, cax=cax, orientation="horizontal")
plt.show()
Edit: Updated for matplotlib version >= 3.
Three great ways to do this have already been shared in this answer.
The matplotlib documentation advises to use inset_locator. This would work as follows:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import numpy as np
rng = np.random.default_rng(1)
fig, ax = plt.subplots(figsize=(4,4))
im = ax.imshow(rng.random((11, 16)))
ax.set_xlabel("x label")
axins = inset_axes(ax,
width="100%",
height="5%",
loc='lower center',
borderpad=-5
)
fig.colorbar(im, cax=axins, orientation="horizontal")

Categories