使用matplotlib中的许多子图改进子图大小/间距

mcs*_*her 260 python matplotlib

这个问题非常相似,但不同之处在于我的身材可以达到需要的大小.

我需要在matplotlib中生成一堆垂直堆叠的图.结果将使用figsave保存并在网页上查看,因此我不关心最终图像的高度,只要子图间隔开,这样它们就不会重叠.

无论我有多大的数字,子图总是似乎重叠.

我的代码目前看起来像

import matplotlib.pyplot as plt
import my_other_module

titles, x_lists, y_lists = my_other_module.get_data()

fig = plt.figure(figsize=(10,60))
for i, y_list in enumerate(y_lists):
    plt.subplot(len(titles), 1, i)
    plt.xlabel("Some X label")
    plt.ylabel("Some Y label")
    plt.title(titles[i])
    plt.plot(x_lists[i],y_list)
fig.savefig('out.png', dpi=100)
Run Code Online (Sandbox Code Playgroud)

Joe*_*ton 357

尝试使用 plt.tight_layout

作为一个简单的例子:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently,  "plt.tight_layout()"

plt.show()
Run Code Online (Sandbox Code Playgroud)

没有严格的布局

在此输入图像描述


紧密的布局 在此输入图像描述

  • 如果你表明你应该在你的情节代码之后执行这个,但是在show()之前就更清楚一点了 (14认同)
  • 所以 `tight_layout()` 使布局......_不太_紧。有趣的名字。 (14认同)
  • 这对我来说效果很好,除了它用我的子图标题覆盖了我的图形标题(`suptitle`)。如果有人遇到类似的问题,这对我的案例有帮助 /sf/answers/3161308601/。即“tight_layout()”的“rect”参数 (7认同)
  • 有用的是,如果添加了轴标题,则可以使用 plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0) 。 (7认同)
  • `tight_layout()`被击中和错过。我一直在试图理解什么都不起作用时(有较大的图间余量)有什么不同-通常是 (4认同)

Cya*_*ook 255

您可以使用plt.subplots_adjust更改子图之间的间距(源)

通话签名:

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
Run Code Online (Sandbox Code Playgroud)

参数含义(和建议的默认值)是:

left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots
hspace = 0.2   # the amount of height reserved for white space between subplots
Run Code Online (Sandbox Code Playgroud)

实际默认值由rc文件控制

  • @mcstrother,如果在显示绘图后单击"调整"按钮,则可以交互式地更改所有这6个参数,然后在找到有效的内容后将它们复制到代码中. (48认同)
  • 我已经尝试过使用hspace,但增加它似乎只会使所有图形更小而不解决重叠问题.我也尝试过使用其他参数,但我不知道左,右,底和顶部实际指定了什么. (3认同)
  • 我没有看到调整按钮。虽然我在 Jupyter 笔记本中。我试过 %matplotlib inline 和 %matplotlib notebook。 (2认同)
  • @MattKleinsmith:调整按钮具有悬停文本“配置子图”,并出现在 Matplotlib 的常规非笔记本使用中。它是此处“软盘”保存按钮左侧的按钮:https://pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/matplotlib-update.jpeg.webp - 注意按钮根据您使用的窗口系统,看起来会有所不同,但它始终位于保存按钮的左侧。 (2认同)
  • 好的!因此,这对我来说可以增加两个子图之间的垂直间距:“plt.subplots_adjust(hspace=0.3)”。我在 `plt.show()` 之前调用它。请注意任何想知道的人:“0.3”的单位是_英寸_,我很确定。我不确定他们如何处理不同的屏幕尺寸...... (2认同)

Ale*_*ord 50

我发现subplots_adjust(hspace = 0.001)最终为我工作了.当我使用space = None时,每个绘图之间仍然有空白区域.将它设置为非常接近零但似乎迫使它们排成一行.我在这里上传的不是最优雅的代码,但你可以看到hspace的工作原理.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tic

fig = plt.figure()

x = np.arange(100)
y = 3.*np.sin(x*2.*np.pi/100.)

for i in range(5):
    temp = 510 + i
    ax = plt.subplot(temp)
    plt.plot(x,y)
    plt.subplots_adjust(hspace = .001)
    temp = tic.MaxNLocator(3)
    ax.yaxis.set_major_locator(temp)
    ax.set_xticklabels(())
    ax.title.set_visible(False)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


The*_*emz 30

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,60))
plt.subplots_adjust( ... )
Run Code Online (Sandbox Code Playgroud)

plt.subplots_adjust方法:

def subplots_adjust(*args, **kwargs):
    """
    call signature::

      subplots_adjust(left=None, bottom=None, right=None, top=None,
                      wspace=None, hspace=None)

    Tune the subplot layout via the
    :class:`matplotlib.figure.SubplotParams` mechanism.  The parameter
    meanings (and suggested defaults) are::

      left  = 0.125  # the left side of the subplots of the figure
      right = 0.9    # the right side of the subplots of the figure
      bottom = 0.1   # the bottom of the subplots of the figure
      top = 0.9      # the top of the subplots of the figure
      wspace = 0.2   # the amount of width reserved for blank space between subplots
      hspace = 0.2   # the amount of height reserved for white space between subplots

    The actual defaults are controlled by the rc file
    """
    fig = gcf()
    fig.subplots_adjust(*args, **kwargs)
    draw_if_interactive()
Run Code Online (Sandbox Code Playgroud)

要么

fig = plt.figure(figsize=(10,60))
fig.subplots_adjust( ... )
Run Code Online (Sandbox Code Playgroud)

图片的大小很重要.

"我已经尝试过使用hspace,但增加它似乎只会使所有图形更小而不解决重叠问题."

因此,为了产生更多的空白空间并保持子图的大小,总图像需要更大.

  • 图片的大小很重要,更大的图片大小可以解决这个问题!设置`plt.figure(figsize =(10,7))`,图片的大小将是`2000 x 1400` pix (2认同)

Cia*_*lsh 23

你可以试试subplot_tool()

plt.subplot_tool()
Run Code Online (Sandbox Code Playgroud)

  • 请参阅https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplot_tool.html (2认同)

Imp*_*est 11

tight_layout现在提供了类似于matplotlib(从2.2版开始)的功能constrained_layout。与相比tight_layout,可以在代码中随时针对单个优化布局调用,这constrained_layout是一个属性,该属性可以处于活动状态,并将在每个绘制步骤之前优化布局。

因此,需要在创建子图之前或期间激活它,例如figure(constrained_layout=True)subplots(constrained_layout=True)

例:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(4,4, constrained_layout=True)

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

constrained_layout也可以通过设置 rcParams

plt.rcParams['figure.constrained_layout.use'] = True
Run Code Online (Sandbox Code Playgroud)

查看新增内容和《受限布局指南》

  • @craq正确,一般来说“contrained_layout”速度较慢,因为如本答案所示,它*在每个绘图步骤之前优化布局*。 (2认同)

Tre*_*ney 9

  • 使用 绘制数据框时解决此问题pandas.DataFrame.plot,该数据框用作matplotlib默认后端。
    • 以下内容适用于kind=指定的内容(例如'bar''scatter''hist'等)。
  • 测试于python 3.8.12, pandas 1.3.4,matplotlib 3.4.3

例子

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# sinusoidal sample data
sample_length = range(1, 15+1)
rads = np.arange(0, 2*np.pi, 0.01)
data = np.array([np.sin(t*rads) for t in sample_length])
df = pd.DataFrame(data.T, index=pd.Series(rads.tolist(), name='radians'), columns=[f'freq: {i}x' for i in sample_length])

# default plot with subplots; each column is a subplot
axes = df.plot(subplots=True)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

调整间距

  • 调整默认参数pandas.DataFrame.plot
    1. 更改figsize:每个子图的宽度为 5,高度为 4 是一个很好的起点。
    2. 更改layout:(行、列)子图的布局。
    3. sharey=True因此sharex=True,每个子图上的冗余标签都不会占用空间。
  • .plot方法返回一个 numpy 数组matplotlib.axes.Axes,该数组应该被展平以便于使用。
  • 用于从其中之一.get_figure()提取图形对象。DataFrame.plotAxes
  • 如果需要的话可以使用fig.tight_layout()
axes = df.plot(subplots=True, layout=(3, 5), figsize=(25, 16), sharex=True, sharey=True)

# flatten the axes array to easily access any subplot
axes = axes.flat

# extract the figure object
fig = axes[0].get_figure()

# use tight_layout
fig.tight_layout()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

df

# display(df.head(3))
         freq: 1x  freq: 2x  freq: 3x  freq: 4x  freq: 5x  freq: 6x  freq: 7x  freq: 8x  freq: 9x  freq: 10x  freq: 11x  freq: 12x  freq: 13x  freq: 14x  freq: 15x
radians                                                                                                                                                            
0.00     0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   0.000000   0.000000   0.000000   0.000000   0.000000   0.000000
0.01     0.010000  0.019999  0.029996  0.039989  0.049979  0.059964  0.069943  0.079915  0.089879   0.099833   0.109778   0.119712   0.129634   0.139543   0.149438
0.02     0.019999  0.039989  0.059964  0.079915  0.099833  0.119712  0.139543  0.159318  0.179030   0.198669   0.218230   0.237703   0.257081   0.276356   0.295520
Run Code Online (Sandbox Code Playgroud)


Tre*_*ney 5

import matplotlib.pyplot as plt

# create the figure with tight_layout=True
fig, axes = plt.subplots(nrows=4, ncols=4, figsize=(8, 8), tight_layout=True)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述