I'm trying to create a figure with some supblots.
Each of the subplots has also 2 subplots side by side.
For that I've used the snippet described here (https://stackoverflow.com/a/67694491).
fig = plt.figure(constrained_layout=True)
subfigs = fig.subfigures(2, 2)
for outerind, subfig in enumerate(subfigs.flat):
subfig.suptitle(f'Subfig {outerind}')
axs = subfig.subplots(1, 2)
for innerind, ax in enumerate(axs.flat):
ax.set_title(f'outer={outerind}, inner={innerind}', fontsize='small')
ax.set_xticks([])
ax.set_yticks([])
ax.set_aspect(1 / ax.get_data_ratio())
plt.show()
The problems is that my subplots have to be squared, and if I resize the whole figure, the gaps between them and the title increases.
fig = plt.figure(constrained_layout=True,figsize=(10,10))
subfigs = fig.subfigures(2, 2)
for outerind, subfig in enumerate(subfigs.flat):
subfig.suptitle(f'Subfig {outerind}')
axs = subfig.subplots(1, 2)
for innerind, ax in enumerate(axs.flat):
ax.set_title(f'outer={outerind}, inner={innerind}', fontsize='small')
ax.set_xticks([])
ax.set_yticks([])
ax.set_aspect(1 / ax.get_data_ratio())
plt.show()
So, how can I keep the aspect I want but with a greater size?
I think the patchworklib module can help you achieve your purpose (I am the developer of the module).
Please refer to the following code. By changing subplotsize value in the code, you can quickly modify the subplot sizes.
import patchworklib as pw
subfigs = []
pw.param["margin"] = 0.2
subplotsize = (1,1) #Please change the value to suit your purpose.
for i in range(4):
ax1 = pw.Brick(figsize=subplotsize)
ax1.set_xticks([])
ax1.set_yticks([])
ax1.set_title("ax{}_1".format(i+1))
ax2 = pw.Brick(figsize=subplotsize)
ax2.set_xticks([])
ax2.set_yticks([])
ax2.set_title("ax{}_2".format(i+1))
ax12 = ax1|ax2
ax12.case.set_title("Subfig-{}".format(i+1), pad=5)
subfigs.append(ax12)
pw.param["margin"] = 0.5
subfig12 = subfigs[0]|subfigs[1]
subfig34 = subfigs[2]|subfigs[3]
fig = (subfig12/subfig34)
fig.savefig("test.pdf")
If subplotsize is (1,1),
If subplotsize is (3,3),
Related
I am new to data visualization world and has been assigned to create a
GUI(graphical user interface) to visualize data and have some fancy controls
in it.
The problem is that I am using subplots using gridspecs and I need to have
equal size buttons in "ax5 subplot" as shown in the figure.
I can't seem to find a solution to access that "ax5" and then divide this
area into 6 equal buttons.
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
def make_ticklabels_invisible(fig):
for i, ax in enumerate(fig.axes):
ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center")
ax.tick_params(labelbottom=False, labelleft=False)
# demo 3 : gridspec with subplotpars set.
fig = plt.figure(facecolor = '#0F0F0F')
fig.suptitle("GridSpec w/ different subplotpars", color= '#e21f1f')
gs1 = GridSpec(3, 3)
gs1.update(left=0.01, right=0.49, wspace=0.05, hspace=0.05)
ax1 = plt.subplot(gs1[:-1, :-1])
ax2 = plt.subplot(gs1[:-1, -1:])
ax3 = plt.subplot(gs1[-1, :])
gs2 = GridSpec(3, 3)
gs2.update(left=0.50, right=0.98, hspace=0.05, wspace=0.05)
ax4 = plt.subplot(gs2[:-2, :])
# need to have six buttons in 5th subplot
ax5 = plt.subplot(gs2[-2:-1, :])
ax6 = plt.subplot(gs2[-1, :])
make_ticklabels_invisible(fig)
pos5 = ax5.get_position()
print(pos5)
plt.show()
I'm trying to remove the white space from the plot that I created:
As it is possible to see, there a big white spot on the right and also on the bottom, how to fix it? Here is my script:
fig = plt.figure(figsize=(7,7))
ax1 = plt.subplot2grid((4,3), (0,0),)
ax2 = plt.subplot2grid((4,3), (1,0),)
ax3 = plt.subplot2grid((4,3), (0,1),)
ax4 = plt.subplot2grid((4,3), (1,1),)
data = self.dframe[i]
tes = print_data(data, self.issues, self.color, self.type_user)
tes.print_top(data=data, top=10, ax=ax1, typegraph="hbar", problem=self.issues[i], tone=self.color[i])
tes.print_top(data=data, top=10, ax=ax2, typegraph="prod_bar", problem=self.issues[i], tone=self.color[i])
tes.print_top(data=data, top=10, ax=ax3, typegraph="reg_hbar", problem=self.issues[i], tone=self.color[i])
tes.print_top(data=data, top=10, ax=ax4, typegraph=self.type_user, problem=self.issues[i], tone=self.color[i])
problem = self.issues[i]
plt.tight_layout()
name = problem + str('.PNG')
plt.close(fig)
fig.savefig(name)
You are creating too many subplots!
If we look at this line:
ax1 = plt.subplot2grid((4,3), (0,0),)
We can see the first argument given to subplot2grid are the dimensions of the subplot grid to be made, in this case 4 rows, and 3 columns. You are then plotting in the subplots in the top left of your figure (the second argument given) which leaves a lot of space that's not used.
So to solve this, reduce the number of subplots by using:
ax1 = plt.subplot2grid((2,2), (0,0),)
Full example:
import numpy as np
import matplotlib.pyplot as plt
data = np.random.randn(25)
fig = plt.figure(figsize=(7,7))
ax1 = plt.subplot2grid((2,2), (0,0),)
ax2 = plt.subplot2grid((2,2), (1,0),)
ax3 = plt.subplot2grid((2,2), (0,1),)
ax4 = plt.subplot2grid((2,2), (1,1),)
ax1.plot(data)
ax2.plot(data)
ax3.plot(data)
ax4.plot(data)
plt.show()
Giving:
you can use
plt.subplots_adjust(left=0.09, bottom=0.07, right=0.98, top=0.97, wspace=0.2 , hspace=0.17 ) to adjust the window.
But the issue is that a lot of the space in your plot is empty
maybe you should change
plt.subplot2grid((4,3)... to plt.subplot2grid((2,2)
Does anyone have a matplotlib example of two plots sharing the y-axis (with no space between the plots) with a single color bar pertaining to both subplots? I have not been able to find examples of this yet.
I created the following code based on your question. Personally I do not like it to have no space between the subplots at all. If you do want to change this at some point all you need to do is to replace plt.subplots_adjust(wspace = -.059) with plt.tight_layout().
Hope this helps
import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
#Random data
data = numpy.random.random((10, 10))
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1, aspect = "equal")
ax2 = fig.add_subplot(1,2,2, aspect = "equal", sharey = ax1) #Share y-axes with subplot 1
#Set y-ticks of subplot 2 invisible
plt.setp(ax2.get_yticklabels(), visible=False)
#Plot data
im1 = ax1.pcolormesh(data)
im2 = ax2.pcolormesh(data)
#Define locations of colorbars for both subplot 1 and 2
divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("right", size="5%", pad=0.05)
divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=0.05)
#Create and remove the colorbar for the first subplot
cbar1 = fig.colorbar(im1, cax = cax1)
fig.delaxes(fig.axes[2])
#Create second colorbar
cbar2 = fig.colorbar(im2, cax = cax2)
#Adjust the widths between the subplots
plt.subplots_adjust(wspace = -.059)
plt.show()
The result is the following:
I am trying to create a figure with 6 sub-plots in python but I am having a problem. Here is a simplified version of my code:
import matplotlib.pyplot as plt
import numpy
g_width = 200
g_height = 200
data = numpy.zeros(g_width*g_height).reshape(g_height,g_width)
ax1 = plt.subplot(231)
im1 = ax1.imshow(data)
ax2 = plt.subplot(232)
im2 = ax2.imshow(data)
ax3 = plt.subplot(233)
im3 = ax3.imshow(data)
ax0 = plt.subplot(234)
im0 = ax0.imshow(data)
ax4 = plt.subplot(235)
im4 = ax4.imshow(data)
ax5 = plt.subplot(236)
ax5.plot([1,2], [1,2])
plt.show()
The above figure has 5 "imshow-based" sub-plots and one simple-data-based sub-plot. Can someone explain to me why the box of the last sub-plot does not have the same size with the other sub-plots? If I replace the last sub-plot with an "imshow-based" sub-plot the problem disappears. Why is this happening? How can I fix it?
The aspect ratio is set to "equal" for the 5imshow()calls (check by callingax1.get_aspect()) while forax5it is set toautowhich gives you the non-square shape you observe. I'm guessingimshow()` defaults to equal while plot does not.
To fix this set all the axis aspect ratios manually e.g when creating the plot ax5 = plt.subplot(236, aspect="equal")
On a side node if your creating many axis like this you may find this useful:
fig, ax = plt.subplots(ncols=3, nrows=2, subplot_kw={'aspect':'equal'})
Then ax is a tuple (in this case ax = ((ax1, ax2, ax3), (ax4, ax5, ax6))) so to plot in the i, j plot just call
ax[i,j].plot(..)
I have 8 plots that I want to compare with 8 different but corresponding plots. So I set up 8 subplots, then try to use axes_grid1.make_axes_locatable to divide the subplots. However, it appears that when I use the new_vertical function it returns something of the type matplotlib.axes.AxesSubplot.
Here's the code I have:
fig = plt.figure()
for i in range(7):
ax = fig.add_subplot(4,2,i+1)
idarray = ice_dict[i]
mdarray = model_dict[i]
side_by_side(ax, idarray, mdarray)
def side_by_side(ax1, idata, mdata):
from mpl_toolkits.axes_grid1 import make_axes_locatable
global mycmap
global ice_dict, titles
divider = make_axes_locatable(ax1)
ax2 = divider.new_vertical(size="100%", pad=0.05)
fig1 = ax1.get_figure()
fig1.add_axes(ax2)
cax1 = divider.append_axes("right", size = "5%", pad= 0.05)
plt.sca(ax1)
im1 = ax1.pcolor(idata, cmap = mycmap)
ax1.set_xlim(space.min(), space.max()+1)
ax1.set_ylim(0, len(idata))
plt.colorbar(im1, cax=cax1)
im2 = ax2.pcolor(mdata, cmap = mycmap)
ax2.set_xlim(space.min(), space.max()+1)
for tl in ax2.get_xticklabels():
tl.set_visible(False)
ax2.set_ylim(0, len(mdata))
ax2.invert_yaxis()
Which produces something like this, where ax2 is on top and ax1 is on bottom in each subplot:
I should probably mention that they're on a different scale so I cant just use the same colorbar for both. Thanks in advance.
tl;dr how can I get a colorbar on ax2, an AxesSubplot, as well as ax1, an Axes? Or is there a better way to get the same look?