I have a set of 12 plots that I want to save as one. The first set is a 3x3 subplot of 9 segments and the 2nd part is a 2x2 subplot of 4 segments.
I've tried to add a subplot(121) between these two and I have tried to use figure(1) and figure(2), but both don't met me save the two images as one big image. Is there an easy way of doing this?
plt.subplot(331)
plt.imshow(getpoly(seg1),origin="lower")
plt.subplot(332)
plt.imshow(getpoly(seg2),origin="lower")
plt.subplot(333)
plt.imshow(getpoly(seg3),origin="lower")
plt.subplot(334)
plt.imshow(getpoly(seg4),origin="lower")
plt.subplot(335)
plt.imshow(getpoly(seg5),origin="lower")
plt.subplot(336)
plt.imshow(getpoly(seg6),origin="lower")
plt.subplot(337)
plt.imshow(getpoly(seg7),origin="lower")
plt.subplot(338)
plt.imshow(getpoly(seg8),origin="lower")
plt.subplot(339)
plt.imshow(getpoly(seg9),origin="lower")
plt.subplot(221)
plt.imshow(h1,origin="lower")
plt.colorbar()
plt.subplot(222)
plt.imshow(h2,origin="lower")
plt.colorbar()
plt.subplot(223)
plt.imshow(getpoly(h2),origin="lower")
plt.colorbar()
plt.subplot(224)
plt.imshow(h1-getpoly(h2),origin="lower")
plt.colorbar()
You would probably want to use gridspec with GridSpecFromSubplotSpec as shown here.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(1, 2)
gs0 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs[0])
gs1 = gridspec.GridSpecFromSubplotSpec(2, 2, subplot_spec=gs[1])
fig = plt.figure()
for i in range(9):
ax = fig.add_subplot(gs0[i//3, i%3])
ax.imshow(np.random.rand(4,4))
ax.set_xticks([]); ax.set_yticks([])
for i in range(4):
ax = fig.add_subplot(gs1[i//2, i%2])
ax.imshow(np.random.rand(4,4))
ax.set_xticks([]); ax.set_yticks([])
plt.show()
Related
I'm learning Python using Jupiter and I'm struggling trying to put the graphs into one figure. Here's what I have so far...
Code for my graphs(I have three of graphs, they only differ in color and lines vs. dot):
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
one = plt.figure()
plt.plot(x_v, y_v, '#008000') #change color using hex strings
plt.xlabel('x')
plt.ylabel('y')
plt.show()
two = plt.figure()
plt.plot(x_v, y_v, linestyle='none', marker='o', markersize=0.5)
plt.show()
three = plt.figure()
plt.plot(x_v, y_v, linestyle='none', marker='o', markersize=0.5, color = 'yellow')
plt.show()
Here's code that I have so far to make it one figure... I was wondering If I should should put it in a np.arange and plot it, but I can't seem to get it to work....
def f(x):
return one
def g(x):
return two
def h(x):
return three
If anyone can help, it'll be of great use! Thank you!
You can use plt.subplots:
fig, (ax1, ax2, ax3) = plt.subplots(figsize=(15, 5), ncols=3)
ax1.plot(x_v, y_v, '#008000')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax2.plot(x_v, y_v, linestyle='none', marker='o', markersize=0.5)
ax3.plot(x_v, y_v, linestyle='none', marker='o', markersize=0.5, color = 'yellow')
Here is one way to approach multiple plots with plt.subplots. I think it is very easy to follow and also gives a lot of control over individual plots:
import numpy as np
import matplotlib.pyplot as plt
#generating test data
x = np.arange(0,9)
y = np.arange(1,10)
#defining figure layout (i.e. rows, columns, size, horizontal and vertical space between subplots
fig,ax = plt.subplots(nrows=2,ncols=2,figsize=(15,7))
plt.subplots_adjust(hspace=0.4,wspace=0.2)
#first subplot (numbering can be read as 1st plot in a grid of 2x2)
plt.subplot(2,2,1)
plt.plot(x,y)
#second subplot in a grid of 2x2
plt.subplot(2,2,2)
plt.plot(x,y,ls='--')
#third subplot in a grid of 2x2
plt.subplot(2,2,3)
plt.scatter(x,y)
#fourth subplot in a grid of 2x2
plt.subplot(2,2,4)
plt.plot(x,y)
plt.tight_layout()
plt.show()
Output:
I have a series of pyplot subplots that I've created using a gridspec. They all have an hspace between them, which is fine, except that I would like to keep three of them without any space. Is there a way to do this? Currently, they look like this:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
grid_spec = gridspec.GridSpec(nrows=10, ncols=10)
grid_spec.update(hspace=1.5)
ax1 = plt.subplot(grid_spec[0:4, :])
ax2 = plt.subplot(grid_spec[4:7, :], sharex=ax1)
# I would like to group the next 3 together
# so that they are stacked top to bottom and side by side
ax3 = plt.subplot(grid_spec[7:8, :5])
ax4 = plt.subplot(grid_spec[8:, :5], sharex=ax3)
ax5 = plt.subplot(grid_spec[8:, 5:6], sharey=ax4)
plt.show()
I would like them to be arranged like this so I can plot the following 2-D KDE diagram and have the relevant 1-D diagrams above and to the right (roughly displaying this sort of data crudely drawn in paint):
I appreciate any help with this one. Can't seem to find documentation on this sort of thing. Thanks!
You can use mpl_toolkits.axes_grid1.make_axes_locatable to subdivide the area of a subplot of a 3 x 2 grid.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure()
gs = fig.add_gridspec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
ax3 = fig.add_subplot(gs[2, 0])
div = make_axes_locatable(ax3)
ax4 = div.append_axes("top", "40%", pad=0.2, sharex=ax3)
ax5 = div.append_axes("right", "25%", pad=0.2, sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
Also, you can create a subgridspec, like
import matplotlib.pyplot as plt
from matplotlib import gridspec
fig = plt.figure()
gs = gridspec.GridSpec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
sub_gs = gridspec.GridSpecFromSubplotSpec(2,2, subplot_spec=gs[2,0], hspace=0.3, wspace=0.1,
height_ratios=[1,3], width_ratios=[3,1])
ax3 = fig.add_subplot(sub_gs[1,0])
ax4 = fig.add_subplot(sub_gs[0,0], sharex=ax3)
ax5 = fig.add_subplot(sub_gs[1,1], sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
In both cases you will probably want to fine tune the parameters a bit. In general, the matplotlib gridspec tutorial gives a nice overview with many examples on this matter.
I am plotting 4 subplots in one figure, and I want to adjust the space in-between evenly.
I tried grid.GridSpec.update.
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
plt.figure(figsize=(8,8))
gs2 = gridspec.GridSpec(2, 2)
gs2.update(wspace=0.01, hspace=0.01)
ax1 = plt.subplot(gs2[0,0],aspect='equal')
ax1.imshow(img)
ax1.axis('off')
ax2 = plt.subplot(gs2[0,1],aspect='equal')
ax2.imshow(img)
ax2.axis('off')
ax3 = plt.subplot(gs2[1,0],aspect='equal')
ax3.imshow(img)
ax3.axis('off')
ax4 = plt.subplot(gs2[1,1],aspect='equal')
ax4.imshow(img)
ax4.axis('off')
The vertical space in-between 2 plots is too big, and it does not change no matter how I adjust gs2.update(hspace= ), as shown below:
It's likely your aspect='equal' that's causing the problem.
Try this
import numpy as np
%matplotlib inline # if in a jupyter notebook like environment
img = np.ones((30, 30))
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True, figsize=(8,8),
gridspec_kw={'wspace': 0.01, 'hspace': 0.01})
axes = axes.ravel()
for ax in axes:
# aspect : ['auto' | 'equal' | scalar], optional, default: None
ax.imshow(img, aspect='auto')
ax.axis('off')
Attached is an image showing the current plot. I am setting fig.subplots_adjust(hspace=0) for the 2D plots to share a common x-axis. I would like to add space between the 3D and 2d plots but am not quite sure how to accomplish this as hspace is set to 0.
fig.subplots_adjust(hspace=0)
for ax in [px_t, py_t, pz_t]:
plt.setp(ax.get_xticklabels(), visible=False)
In this case, it's best to use two separate GridSpec instances. That way you can have two separate hspace parameters. Alternatively, you can manually place the top axes.
As an example of the first option:
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
fig = plt.figure(figsize=(8, 10))
gs1 = plt.GridSpec(2, 1, hspace=0.2)
gs2 = plt.GridSpec(8, 1, hspace=0)
ax1 = fig.add_subplot(gs1[0], projection='3d')
ax1.plot(range(10), range(10), range(10))
ax = fig.add_subplot(gs2[4])
lower_axes = [ax]
for i in range(4, 8):
if i > 4:
ax = fig.add_subplot(gs2[i], sharex=lower_axes[0])
ax.plot(range(10))
ax.locator_params(axis='y', nbins=5, prune='both')
lower_axes.append(ax)
for ax in lower_axes:
ax.label_outer()
plt.show()
I am trying to add a single colorbar for two matshows using mainly the code at here and here.
My code is the following now, but the problem is that the colorbar moderates the size of the plot on the right. How can I prevent that?
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
# Generate some data that where each slice has a different range
# (The overall range is from 0 to 2)
data = np.random.random((2,10,10))
data *= np.array([1.5, 2.0])[:,None,None]
# Plot each slice as an independent subplot
fig, axes = plt.subplots(nrows=1, ncols=2)
for dat, ax in zip(data, axes.flat):
# The vmin and vmax arguments specify the color limits
im = ax.imshow(dat, vmin=0, vmax=2)
# Make an axis for the colorbar on the right side
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
fig.colorbar(im, cax=cax)
plt.tight_layout()
plt.show()
There are a couple approaches in the answers to Matplotlib 2 Subplots, 1 Colorbar. The last is simplest but doesn't work for me (the imshow plots are the same size, but both shorter than the colorbar). You could also run the colorbar under the images:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.random.random((2,10,10))
data *= np.array([1.5, 2.0])[:,None,None]
fig, axes = plt.subplots(nrows=1, ncols=2)
for dat, ax in zip(data, axes.flat):
im = ax.imshow(dat, vmin=0, vmax=2)
fig.colorbar(im, ax=axes.ravel().tolist(), orientation='horizontal')
plt.show()