Matplotlib 图形尺寸调整:全面指南与实用技巧
参考:How to change the size of figures drawn with matplotlib
Matplotlib 是 Python 中最流行的数据可视化库之一,它提供了丰富的功能来创建各种类型的图表和图形。在使用 Matplotlib 时,控制图形的尺寸是一个重要的方面,因为它直接影响到图形的清晰度、可读性和整体呈现效果。本文将详细介绍如何在 Matplotlib 中更改图形尺寸,包括各种方法、技巧和最佳实践。
1. 基本图形尺寸设置
在 Matplotlib 中,最基本的设置图形尺寸的方法是使用 figure()
函数的 figsize
参数。这个参数接受一个元组,其中包含宽度和高度(以英寸为单位)。
import matplotlib.pyplot as plt
import numpy as np
# 创建一个 8x6 英寸的图形
plt.figure(figsize=(8, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('How to change figure size - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
Output:
在这个例子中,我们创建了一个 8 英寸宽、6 英寸高的图形。figsize=(8, 6)
参数设置了这个尺寸。这是最直接和常用的方法,适用于大多数简单的绘图需求。
2. 使用 rcParams 全局设置图形尺寸
如果你想在整个脚本或会话中统一设置所有图形的默认尺寸,可以使用 plt.rcParams
。这种方法可以避免在每次创建图形时都重复设置尺寸。
import matplotlib.pyplot as plt
import numpy as np
# 全局设置图形尺寸
plt.rcParams['figure.figsize'] = [10, 8]
# 创建图形(将使用默认尺寸)
plt.figure()
x = np.linspace(0, 10, 100)
y = np.cos(x)
plt.plot(x, y)
plt.title('Global figure size setting - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
Output:
在这个例子中,我们通过 plt.rcParams['figure.figsize'] = [10, 8]
全局设置了图形尺寸为 10×8 英寸。这之后创建的所有图形都将默认使用这个尺寸,除非在 figure()
函数中特别指定其他尺寸。
3. 使用 subplots() 函数设置图形尺寸
subplots()
函数是创建图形和轴对象的另一种常用方法,它也允许你在创建时设置图形尺寸。
import matplotlib.pyplot as plt
import numpy as np
# 创建一个 9x7 英寸的图形和一组轴
fig, ax = plt.subplots(figsize=(9, 7))
x = np.linspace(0, 10, 100)
y = np.tan(x)
ax.plot(x, y)
ax.set_title('Figure size with subplots() - how2matplotlib.com')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
plt.show()
Output:
这个例子展示了如何使用 subplots()
函数创建一个 9×7 英寸的图形。figsize=(9, 7)
参数直接传递给 subplots()
函数。这种方法特别适用于创建包含多个子图的复杂图形布局。
4. 动态调整图形尺寸
有时,你可能需要根据数据或其他条件动态调整图形尺寸。这可以通过在代码中计算尺寸并将其传递给 figure()
或 subplots()
函数来实现。
import matplotlib.pyplot as plt
import numpy as np
def calculate_figure_size(data_length):
base_size = 5
return (base_size + data_length / 20, base_size)
x = np.linspace(0, 20, 200)
y = np.exp(-x/10) * np.sin(2*x)
fig_size = calculate_figure_size(len(x))
plt.figure(figsize=fig_size)
plt.plot(x, y)
plt.title('Dynamic figure size - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
Output:
在这个例子中,我们定义了一个 calculate_figure_size()
函数,它根据数据的长度动态计算图形的宽度。这种方法可以确保图形的宽度随着数据量的增加而适当增加,从而保持可读性。
5. 调整 DPI(每英寸点数)
除了直接更改图形的物理尺寸,你还可以通过调整 DPI(每英寸点数)来影响图形的大小和质量。DPI 越高,图形在相同的物理尺寸下会包含更多的像素,从而提高清晰度。
import matplotlib.pyplot as plt
import numpy as np
# 创建一个高 DPI 的图形
plt.figure(figsize=(8, 6), dpi=300)
x = np.linspace(0, 10, 100)
y = np.sin(x) * np.exp(-x/10)
plt.plot(x, y)
plt.title('High DPI figure - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
Output:
这个例子创建了一个 8×6 英寸、300 DPI 的高分辨率图形。增加 DPI 可以提高图形的清晰度,特别是在打印或需要高质量图像输出时非常有用。
6. 使用英寸以外的单位
虽然 Matplotlib 默认使用英寸作为尺寸单位,但有时你可能更习惯使用其他单位,如厘米。你可以轻松地进行单位转换。
import matplotlib.pyplot as plt
import numpy as np
# 将厘米转换为英寸
cm_to_inch = 1/2.54
# 创建一个 20x15 厘米的图形
plt.figure(figsize=(20*cm_to_inch, 15*cm_to_inch))
x = np.linspace(0, 10, 100)
y = np.sin(x) + np.random.normal(0, 0.1, 100)
plt.scatter(x, y)
plt.title('Figure size in centimeters - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
Output:
这个例子展示了如何创建一个 20×15 厘米的图形。我们首先定义了一个转换因子 cm_to_inch
,然后在 figsize
参数中使用这个因子将厘米转换为英寸。
7. 调整图形尺寸以适应屏幕
在某些情况下,你可能想要创建一个适应当前屏幕尺寸的图形。这可以通过使用 plt.get_current_fig_manager()
来实现。
import matplotlib.pyplot as plt
import numpy as np
# 创建图形
fig = plt.figure()
# 获取屏幕尺寸并设置图形大小
manager = plt.get_current_fig_manager()
manager.resize(*manager.window.maxsize())
x = np.linspace(0, 10, 100)
y = np.sin(x) * np.cos(x)
plt.plot(x, y)
plt.title('Full screen figure - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.show()
这个例子创建了一个全屏图形。manager.resize(*manager.window.maxsize())
将图形调整为当前屏幕的最大尺寸。请注意,这种方法的效果可能因操作系统和后端而异。
8. 使用 tight_layout() 自动调整子图布局
当你有多个子图或图形元素时,可能需要调整它们的布局以避免重叠。tight_layout()
函数可以自动调整子图之间的间距。
import matplotlib.pyplot as plt
import numpy as np
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 10))
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
ax1.plot(x, y1)
ax1.set_title('Subplot 1 - how2matplotlib.com')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')
ax2.plot(x, y2)
ax2.set_title('Subplot 2 - how2matplotlib.com')
ax2.set_xlabel('X-axis')
ax2.set_ylabel('Y-axis')
plt.tight_layout()
plt.show()
Output:
在这个例子中,我们创建了两个子图。使用 plt.tight_layout()
可以自动调整子图之间的间距,确保标题、标签等不会重叠。
9. 使用 constrained_layout 进行更精细的布局控制
constrained_layout
是 Matplotlib 中一个更高级的布局管理器,它可以提供比 tight_layout()
更精细的控制。
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)
x = np.linspace(0, 10, 100)
for ax in axs.flat:
ax.plot(x, np.random.rand(100))
ax.set_title('Subplot - how2matplotlib.com')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
plt.show()
Output:
这个例子创建了一个 2×2 的子图网格,并使用 constrained_layout=True
来自动调整布局。这种方法特别适用于复杂的图形布局,可以有效避免标签重叠和空间浪费。
10. 保存图形时调整尺寸
当保存图形到文件时,你可能想要指定不同于显示时的尺寸。这可以通过 savefig()
函数的参数来实现。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x) * np.exp(-x/10)
plt.figure(figsize=(8, 6))
plt.plot(x, y)
plt.title('Saving with different size - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
# 保存为 10x8 英寸的图片
plt.savefig('output_figure.png', dpi=300, bbox_inches='tight', figsize=(10, 8))
plt.show()
在这个例子中,我们创建了一个 8×6 英寸的图形,但在保存时将其调整为 10×8 英寸。bbox_inches='tight'
参数确保图形的所有部分都被包含在保存的图像中。
11. 使用 GridSpec 进行复杂布局
对于更复杂的图形布局,GridSpec
提供了强大的控制能力,允许你创建不规则的子图网格。
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
fig = plt.figure(figsize=(12, 8))
gs = gridspec.GridSpec(3, 3)
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :-1])
ax3 = fig.add_subplot(gs[1:, -1])
ax4 = fig.add_subplot(gs[-1, 0])
ax5 = fig.add_subplot(gs[-1, -2])
x = np.linspace(0, 10, 100)
ax1.plot(x, np.sin(x))
ax1.set_title('GridSpec layout - how2matplotlib.com')
ax2.plot(x, np.cos(x))
ax3.plot(x, np.tan(x))
ax4.plot(x, np.exp(x))
ax5.plot(x, np.log(x))
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何使用 GridSpec
创建一个复杂的布局,其中子图的大小和位置都是不规则的。这种方法允许你创建非常灵活和定制化的图形布局。
12. 调整图形边距
有时你可能需要调整图形的边距,以便为标题、标签或其他元素留出更多空间。这可以通过 subplots_adjust()
函数来实现。
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(10, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x) * np.exp(-x/10)
plt.plot(x, y)
plt.title('Adjusted margins - how2matplotlib.com', fontsize=16)
plt.xlabel('X-axis', fontsize=14)
plt.ylabel('Y-axis', fontsize=14)
# 调整边距
plt.subplots_adjust(top=0.85, bottom=0.15, left=0.1, right=0.95)
plt.show()
Output:
在这个例子中,我们使用 subplots_adjust()
函数调整了图形的上下左右边距。这对于为大标题或长标签留出空间特别有用。
13. 使用 aspect 参数控制纵横比
在某些情况下,控制图形的纵横比(aspect ratio)可能比精确控制尺寸更重要。Matplotlib 提供了 aspect
参数来实现这一点。
import matplotlib.pyplot as plt
import numpy as np
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax1.plot(x, y)
ax1.set_title('Default aspect - how2matplotlib.com')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')
ax2.plot(x, y)
ax2.set_aspect('equal')
ax2.set_title('Equal aspect - how2matplotlib.com')
ax2.set_xlabel('X-axis')
ax2.set_ylabel('Y-axis')
plt.tight_layout()
plt.show()
Output:
这个例子展示了默认纵横比和使用 set_aspect('equal')
设置等比例纵横比的区别。等比例纵横比在绘制某些类型的图形(如圆形或正方形)时特别有用。
14. 使用 bbox_inches 参数裁剪多余的空白
当保存图形时,有时可能会出现不必要的空白边距。使用 bbox_inches='tight'
参数可以自动裁剪这些空白。
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(8, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x) + np.random.normal(0, 0.1, 100)
plt.scatter(x, y)
plt.title('Trimmed white space - how2matplotlib.com')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
# 保存图形,裁剪多余的空白
plt.savefig('trimmed_figure.png', bbox_inches='tight')
plt.show()
Output:
这个例子展示了如何在保存图形时使用 bbox_inches='tight'
参数来自动裁剪多余的空白边距,从而得到更紧凑的图形。
15. 使用 set_size_inches() 方法动态调整图形大小
有时,你可能需要在创建图形后动态调整其大小。set_size_inches()
方法提供了这种灵活性。
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x) * np.cos(x)
ax.plot(x, y)
ax.set_title('Initial size - how2matplotlib.com')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
plt.show()
# 动态调整图形大小
fig.set_size_inches(10, 4)
ax.set_title('Resized figure - how2matplotlib.com')
plt.show()
这个例子首先创建了一个 8×6 英寸的图形,然后使用 set_size_inches()
方法将其调整为 10×4 英寸。这种方法在交互式环境中特别有用,可以根据需要快速调整图形大小。
16. 使用 plt.figure() 的 dpi 参数控制图形分辨率
DPI(每英寸点数)不仅影响图形的质量,还会影响其在屏幕上显示的大小。通过调整 DPI,你可以在保持物理尺寸不变的情况下改变图形的像素尺寸。
import matplotlib.pyplot as plt
import numpy as np
# 创建两个具有不同 DPI 的图形
fig1 = plt.figure(figsize=(8, 6), dpi=100)
fig2 = plt.figure(figsize=(8, 6), dpi=200)
x = np.linspace(0, 10, 100)
y = np.sin(x)
for fig in [fig1, fig2]:
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_title(f'Figure with DPI {fig.dpi} - how2matplotlib.com')
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
plt.show()
Output:
这个例子创建了两个物理尺寸相同但 DPI 不同的图形。第一个图形的 DPI 为 100,第二个为 200。尽管两个图形的物理尺寸相同,但第二个图形在屏幕上会显示得更大,因为它包含了更多的像素。
17. 使用 plt.axes() 在图形中创建自定义位置的子图
有时,你可能需要在图形中的特定位置创建子图。plt.axes()
函数允许你精确控制子图的位置和大小。
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10, 8))
# 主图
ax_main = fig.add_axes([0.1, 0.1, 0.8, 0.8])
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax_main.plot(x, y)
ax_main.set_title('Main plot - how2matplotlib.com')
# 右上角的小图
ax_small = fig.add_axes([0.65, 0.65, 0.25, 0.25])
ax_small.plot(x, np.cos(x))
ax_small.set_title('Small plot')
plt.show()
Output:
在这个例子中,我们使用 fig.add_axes()
方法创建了两个子图。第一个子图占据了图形的大部分区域,而第二个子图被放置在右上角。参数列表 [left, bottom, width, height]
定义了子图在图形中的位置和大小,这些值都是相对于整个图形的比例。
18. 使用 plt.subplot2grid() 创建不规则网格布局
subplot2grid()
函数提供了另一种创建复杂布局的方法,特别适用于需要跨越多个网格单元的子图。
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(12, 8))
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))
x = np.linspace(0, 10, 100)
ax1.plot(x, np.sin(x))
ax1.set_title('subplot2grid layout - how2matplotlib.com')
ax2.plot(x, np.cos(x))
ax3.plot(x, np.tan(x))
ax4.plot(x, np.exp(x))
ax5.plot(x, np.log(x))
plt.tight_layout()
plt.show()
Output:
这个例子使用 subplot2grid()
创建了一个 3×3 的网格,并在其中放置了不同大小和位置的子图。这种方法提供了极大的灵活性,允许你创建复杂的、非对称的图形布局。
19. 使用 plt.subplot() 快速创建子图网格
对于简单的子图布局,plt.subplot()
提供了一种快速且直观的方法来创建子图网格。
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(12, 8))
x = np.linspace(0, 10, 100)
plt.subplot(2, 2, 1)
plt.plot(x, np.sin(x))
plt.title('Subplot 1 - how2matplotlib.com')
plt.subplot(2, 2, 2)
plt.plot(x, np.cos(x))
plt.title('Subplot 2 - how2matplotlib.com')
plt.subplot(2, 2, 3)
plt.plot(x, np.exp(x))
plt.title('Subplot 3 - how2matplotlib.com')
plt.subplot(2, 2, 4)
plt.plot(x, np.log(x))
plt.title('Subplot 4 - how2matplotlib.com')
plt.tight_layout()
plt.show()
Output:
这个例子创建了一个 2×2 的子图网格。plt.subplot(2, 2, n)
中的参数分别表示行数、列数和当前子图的索引。这种方法特别适合快速创建规则的子图布局。
20. 使用 plt.suptitle() 为整个图形添加总标题
当你有多个子图时,可能需要为整个图形添加一个总标题。plt.suptitle()
函数可以实现这一点。
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('Figure with multiple subplots - how2matplotlib.com', fontsize=16)
x = np.linspace(0, 10, 100)
axs[0, 0].plot(x, np.sin(x))
axs[0, 0].set_title('Subplot 1')
axs[0, 1].plot(x, np.cos(x))
axs[0, 1].set_title('Subplot 2')
axs[1, 0].plot(x, np.exp(x))
axs[1, 0].set_title('Subplot 3')
axs[1, 1].plot(x, np.log(x))
axs[1, 1].set_title('Subplot 4')
plt.tight_layout()
plt.subplots_adjust(top=0.88) # 为总标题留出空间
plt.show()
Output:
在这个例子中,我们使用 fig.suptitle()
为整个图形添加了一个总标题。注意,我们还使用了 plt.subplots_adjust(top=0.88)
来为总标题留出足够的空间,防止它与子图重叠。
总结起来,Matplotlib 提供了多种方法来控制图形的尺寸和布局。从简单的 figsize
参数设置,到复杂的 GridSpec 布局,再到动态调整和保存时的尺寸控制,你可以根据具体需求选择最合适的方法。掌握这些技巧将帮助你创建既美观又信息丰富的数据可视化图表。