[英]Embedding several inset axes in another axis using matplotlib
Is it possible to embed a changing number of plots in a matplotlib axis? 是否可以在matplotlib轴中嵌入数量不断变化的图? For example, the inset_axes
method is used to place inset axes inside parent axes: 例如, inset_axes
方法用于将插入轴放置在父轴内:
However, I have several rows of plots and I want to include some inset axes inside the last axis object of each row. 但是,我有多行绘图,我想在每行的最后一个轴对象内包括一些插入轴。
fig, ax = plt.subplots(2,4, figsize=(15,15))
for i in range(2):
ax[i][0].plot(np.random.random(40))
ax[i][2].plot(np.random.random(40))
ax[i][3].plot(np.random.random(40))
# number of inset axes
number_inset = 5
for j in range(number_inset):
ax[i][4].plot(np.random.random(40))
Here instead of the 5 plots drawn in the last column, I want several inset axes containing a plot. 在这里,而不是最后一列中绘制的5个图,我想要几个插入轴包含一个图。 Something like this: 像这样:
The reason for this is that every row refers to a different item to be plotted and the last column is supposed to contain the components of such item. 这样做的原因是,每一行都涉及要绘制的不同项目,而最后一列应该包含该项目的组件。 Is there a way to do this in matplotlib or maybe an alternative way to visualize this? 有没有办法在matplotlib中做到这一点,或者有一种可视化的替代方法?
Thanks 谢谢
As @hitzg mentioned, the most common way to accomplish something like this is to use GridSpec
. 如@hitzg所述,完成此类操作的最常见方法是使用GridSpec
。 GridSpec
creates an imaginary grid object that you can slice to produce subplots. GridSpec
创建一个虚构的网格对象,您可以对其进行切片以生成子图。 It's an easy way to align fairly complex layouts that you want to follow a regular grid. 这是一种易于对齐的复杂布局,可以遵循常规网格的简单方法。
However, it may not be immediately obvious how to use it in this case. 但是,在这种情况下如何使用它可能不是立即显而易见的。 You'll need to create a GridSpec
with numrows * numinsets
rows by numcols
columns and then create the "main" axes by slicing it with intervals of numinsets
. 你需要创建一个GridSpec
与numrows * numinsets
按行numcols
列,然后通过与间隔切片它创建“主”轴numinsets
。
In the example below (2 rows, 4 columns, 3 insets), we'd slice by gs[:3, 0]
to get the upper left "main" axes, gs[3:, 0]
to get the lower left "main" axes, gs[:3, 1]
to get the next upper axes, etc. For the insets, each one is gs[i, -1]
. 在下面的示例中(2行,4列,3个插图),我们对gs[:3, 0]
进行切片以获取左上方的“主轴”,对gs[3:, 0]
进行切片以获取左下方的“主轴”主”轴, gs[:3, 1]
获取下一个上轴,等等。对于插图,每个是gs[i, -1]
。
As a complete example: 举一个完整的例子:
import numpy as np
import matplotlib.pyplot as plt
def build_axes_with_insets(numrows, numcols, numinsets, **kwargs):
"""
Makes a *numrows* x *numcols* grid of subplots with *numinsets* subplots
embedded as "sub-rows" in the last column of each row.
Returns a figure object and a *numrows* x *numcols* object ndarray where
all but the last column consists of axes objects, and the last column is a
*numinsets* length object ndarray of axes objects.
"""
fig = plt.figure(**kwargs)
gs = plt.GridSpec(numrows*numinsets, numcols)
axes = np.empty([numrows, numcols], dtype=object)
for i in range(numrows):
# Add "main" axes...
for j in range(numcols - 1):
axes[i, j] = fig.add_subplot(gs[i*numinsets:(i+1)*numinsets, j])
# Add inset axes...
for k in range(numinsets):
m = k + i * numinsets
axes[i, -1][k] = fig.add_subplot(gs[m, -1])
return fig, axes
def plot(axes):
"""Recursive plotting function just to put something on each axes."""
for ax in axes.flat:
data = np.random.normal(0, 1, 100).cumsum()
try:
ax.plot(data)
ax.set(xticklabels=[], yticklabels=[])
except AttributeError:
plot(ax)
fig, axes = build_axes_with_insets(2, 4, 3, figsize=(12, 6))
plot(axes)
fig.tight_layout()
plt.show()
This is what I did to obtain the same result without setting the number of inset plots in advance. 这是我在不预先设置插图数的情况下获得相同结果的方法。
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
fig = plt.figure(figsize=(12,6))
nrows = 2
ncols = 4
# changing the shape of GridSpec's output
outer_grid = gridspec.GridSpec(nrows, ncols)
grid = []
for i in range(nrows*ncols):
grid.append(outer_grid[i])
outer_grid = np.array(grid).reshape(nrows,ncols)
for i in range(nrows):
inner_grid_1 = gridspec.GridSpecFromSubplotSpec(1, 1,
subplot_spec=outer_grid[i][0])
ax = plt.Subplot(fig, inner_grid_1[0])
ax.plot(np.random.normal(0,1,50).cumsum())
fig.add_subplot(ax)
inner_grid_2 = gridspec.GridSpecFromSubplotSpec(1, 1,
subplot_spec=outer_grid[i][1])
ax2 = plt.Subplot(fig, inner_grid_2[0])
ax2.plot(np.random.normal(0,1,50).cumsum())
fig.add_subplot(ax2)
inner_grid_3 = gridspec.GridSpecFromSubplotSpec(1, 1,
subplot_spec=outer_grid[i][2])
ax3 = plt.Subplot(fig, inner_grid_3[0])
ax3.plot(np.random.normal(0,1,50).cumsum())
fig.add_subplot(ax3)
# this value can be set based on some other calculation depending
# on each row
numinsets = 3
inner_grid_4 = gridspec.GridSpecFromSubplotSpec(numinsets, 1,
subplot_spec=outer_grid[i][3])
# Adding subplots to the last inner grid
for j in range(inner_grid_4.get_geometry()[0]):
ax4 = plt.Subplot(fig, inner_grid_4[j])
ax4.plot(np.random.normal(0,1,50).cumsum())
fig.add_subplot(ax4)
# Removing labels
for ax in fig.axes:
ax.set(xticklabels=[], yticklabels=[])
fig.tight_layout()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.