多个子图的GridSpec“正在清除包含传递轴的图形”

Posted

技术标签:

【中文标题】多个子图的GridSpec“正在清除包含传递轴的图形”【英文标题】:GridSpec of multiple subplots "the figure containing the passed axes is being cleared" 【发布时间】:2015-11-29 01:10:20 【问题描述】:

我有 4 个不同的df.hist(columns=, by=),我想将它们插入到 GridSpec(2, 2) 中。

每一个看起来都是这样的:

代码如下:

stuff = [df1, df2, df4, df3]
col = ['blue', 'orange', 'grey', 'green']
fig = plt.figure(figsize=(10,10))
gs = gridspec.GridSpec(2, 2)

for i in range(0, len(stuff)):
    ax = plt.subplot(gs[i])
    stuff[i].hist(column='quanti_var', by=stuff[i].quali_var, alpha=.5, color=col[i], ax=ax)

我收到以下用户警告:

C:\Anaconda3\lib\site-packages\pandas\tools\plotting.py:3234: UserWarning: To output multiple subplots, the figure containing the passed axes is being cleared
  "is being cleared", UserWarning)

而不是我正在寻找的输出:

我尝试了几件事,包括使用SubplotSpec,但没有成功。有什么想法吗?

谢谢你们把你的神经元借给我!

【问题讨论】:

能够做到这一点很好,但不幸的是现在我不认为是不可能的(至少使用这个界面)。看看plotting.py,pandas 在做分组直方图时总是想制作自己的子图。因此,您只会得到图中的最后一个 DataFrame... 【参考方案1】:

解决方案是将pd.DataFrame.hist()返回的matplotlibAxes对象放入所需布局的图形中。不幸的是,将新的Axes 对象放入现有的Figure 有点麻烦。

GridSpec布局

使用嵌套的matplotlib.gridspec.GridSpecs 创建您想要的布局并不太复杂(示例参见here)。像这样。

import matplotlib.gridspec as gs

num_outer_columns = 2
num_outer_rows = 2
num_inner_columns = 2
num_inner_rows = 3

outer_layout = gs.GridSpec(num_outer_rows, num_outer_columns)
inner_layout = []

for row_num in range(num_outer_rows):
    inner_layout.append([])
    for col_num in range(num_outer_columns):
        inner_layout[row_num].append(
            gs.GridSpecFromSubplotSpec(
                num_inner_rows, 
                num_inner_columns, 
                outer_layout[row_num, col_num]
            )
        )

您可以使用ax = plt.subplot(inner_layout[outer_row_num][outer_col_num][inner_row_num, inner_col_num]) 在此网格内创建子图,并存储正确定位的axs 以供以后使用。

Axes 复制到现有的Figure

您的df.hist() 调用将产生如下内容:

In [1]: dframe.hist(column=x, by=y)
Out[1]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x1189be160>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x118e3eb50>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x118e74d60>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x118ea8340>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x118e76d62>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x118ea9350>]],
      dtype=object)

现在你只需要用上面返回的AxesSubplot 对象替换之前使用inner_layout 定位的ax 对象。不幸的是,没有方便的ax.from_axes(other_ax) 方法来执行此操作,因此您必须按照this answer 手动复制df.hist() 返回的Axes

【讨论】:

以上是关于多个子图的GridSpec“正在清除包含传递轴的图形”的主要内容,如果未能解决你的问题,请参考以下文章

如何使子图的大小相等?

Matplotlib 使用GridSpec和其他功能自定义图形布局

python中不均匀的子图

Matplotlib 不同大小的子图

每个子图规格的标题(子图内的子图)

多个绘图子图的单个滑块