如何更改用 Matplotlib 绘制的图形的大小?

2024-11-21 08:33:00
admin
原创
4
摘要:问题描述:如何更改用 Matplotlib 绘制的图形的大小?解决方案 1:figure告诉您呼叫签名:from matplotlib.pyplot import figure figure(figsize=(8, 6), dpi=80) figure(figsize=(1,1))将创建一个英寸乘以英寸的图...

问题描述:

如何更改用 Matplotlib 绘制的图形的大小?


解决方案 1:

figure告诉您呼叫签名:

from matplotlib.pyplot import figure

figure(figsize=(8, 6), dpi=80)

figure(figsize=(1,1))将创建一个英寸乘以英寸的图像,除非您还给出不同的 dpi 参数,否则它将是 80 x 80 像素。

解决方案 2:

如果您已经创建了图形,您可以使用figure.set_size_inches来调整图形大小:

fig = matplotlib.pyplot.gcf()
fig.set_size_inches(18.5, 10.5)
fig.savefig('test2png.png', dpi=100)

要将尺寸变化传播到现有的 GUI 窗口,请添加forward=True

fig.set_size_inches(18.5, 10.5, forward=True)

此外,正如Erik Shilts在评论中提到的,您还可以使用figure.set_dpi“以每英寸点数为单位设置图形的分辨率”

fig.set_dpi(100)

解决方案 3:

使用 plt.rcParams

如果您想在不使用图形环境的情况下更改尺寸,也可以使用这个解决方法。例如plt.plot(),您可以设置一个包含宽度和高度的元组。

import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (20,3)

这在你进行内联绘图时非常有用(例如,使用IPython Notebook)。正如asmaier 所注意到的,最好不要将此语句放在 imports 语句的同一单元格中。

要将全局图形尺寸重置为后续绘图的默认值:

plt.rcParams["figure.figsize"] = plt.rcParamsDefault["figure.figsize"]

转换为厘米

figsize元组接受英寸,因此如果要以厘米为单位设置,则必须将其除以 2.54。 看看这个问题。

解决方案 4:

弃用说明:

根据官方 Matplotlib 指南pylab,不再建议使用该模块。请考虑改用该模块,如另一个答案matplotlib.pyplot所述。

以下似乎有效:

from pylab import rcParams
rcParams['figure.figsize'] = 5, 10

这使得图形的宽度为 5 英寸,高度为 10英寸

然后 Figure 类使用它作为其某个参数的默认值。

解决方案 5:

如果您正在寻找一种方法来改变Pandas中的图形大小,您可以执行以下操作:

df['some_column'].plot(figsize=(10, 5))

其中df是 Pandas 数据框。或者,使用现有图形或轴:

fig, ax = plt.subplots(figsize=(10, 5))
df['some_column'].plot(ax=ax)

如果您想更改默认设置,您可以执行以下操作:

import matplotlib

matplotlib.rc('figure', figsize=(10, 5))

有关更多详细信息,请查看文档:pd.DataFrame.plot

解决方案 6:

Google 中的第一个链接'matplotlib figure size'是AdjustingImageSize(页面的 Google 缓存)。

这是来自上述页面的测试脚本。它创建了test[1-3].png同一张图片的不同大小的文件:

#!/usr/bin/env python
"""
This is a small demo file that helps teach how to adjust figure sizes
for matplotlib

"""

import matplotlib
print "using MPL version:", matplotlib.__version__
matplotlib.use("WXAgg") # do this before pylab so you don'tget the default back end.

import pylab
import numpy as np

# Generate and plot some simple data:
x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)

pylab.plot(x,y)
F = pylab.gcf()

# Now check everything with the defaults:
DPI = F.get_dpi()
print "DPI:", DPI
DefaultSize = F.get_size_inches()
print "Default size in Inches", DefaultSize
print "Which should result in a %i x %i Image"%(DPI*DefaultSize[0], DPI*DefaultSize[1])
# the default is 100dpi for savefig:
F.savefig("test1.png")
# this gives me a 797 x 566 pixel image, which is about 100 DPI

# Now make the image twice as big, while keeping the fonts and all the
# same size
F.set_size_inches( (DefaultSize[0]*2, DefaultSize[1]*2) )
Size = F.get_size_inches()
print "Size in Inches", Size
F.savefig("test2.png")
# this results in a 1595x1132 image

# Now make the image twice as big, making all the fonts and lines
# bigger too.

F.set_size_inches( DefaultSize )# resetthe size
Size = F.get_size_inches()
print "Size in Inches", Size
F.savefig("test3.png", dpi = (200)) # change the dpi
# this also results in a 1595x1132 image, but the fonts are larger.

输出:

using MPL version: 0.98.1
DPI: 80
Default size in Inches [ 8.  6.]
Which should result in a 640 x 480 Image
Size in Inches [ 16.  12.]
Size in Inches [ 16.  12.]

两点说明:

  1. 模块注释和实际输出不同。

  2. 这个答案可以轻松地将所有三幅图像合并到一个图像文件中,以查看尺寸的差异。

解决方案 7:

调整figsize=中的参数,它与这个答案matplotlib.pyplot.figure类似,但使用标准导入别名,而不是直接从命名空间导入。plt`figure`pyplot

import numpy as np
import matplotlib.pyplot as plt

N = 50
np.random.seed(2022)  # creates a repetitive sample data
x = np.random.rand(N)
y = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2

fig = plt.figure(figsize=(10, 10))
plt.scatter(x, y, s=area, alpha=0.5)
plt.show()

没有fig = plt.figure(figsize=(10, 10))

在此处输入图片描述

fig = plt.figure(figsize=(10, 10))

在此处输入图片描述

解决方案 8:

您可以简单地使用(来自matplotlib.figure.Figure):

fig.set_size_inches(width,height)

从 Matplotlib 2.0.0 开始,对画布的更改将立即可见,因为forward关键字默认为True

如果你只想改变宽度高度而不是两者,你可以使用

fig.set_figwidth(val)或者fig.set_figheight(val)

这些也将立即更新您的画布,但仅限于 Matplotlib 2.2.0 及更新版本。

对于旧版本

您需要forward=True明确指定才能在早于上述指定的版本中实时更新画布。请注意,set_figwidth和函数在早于 Matplotlib 1.5.0 的版本中set_figheight不支持该参数。forward

解决方案 9:

这对我来说很有效:

from matplotlib import pyplot as plt

F = plt.gcf()
Size = F.get_size_inches()
F.set_size_inches(Size[0]*2, Size[1]*2, forward=True) # Set forward to True to resize window along with plot in figure.
plt.show() # Or plt.imshow(z_array) if using an animation, where z_array is a matrix or NumPy array

这个论坛帖子可能也有帮助:调整图形窗口大小

解决方案 10:

比较以像素为单位设置精确图像大小的不同方法

本回答将重点关注:

  • savefig:如何保存到文件,而不仅仅是显示在屏幕上

  • 以像素为单位设置大小

这里对我曾经尝试过的一些方法进行了快速比较,并通过图像展示了它们的效果。

当前状态摘要:事情很混乱,我不确定这是否是一个根本的限制,或者用例是否没有得到开发人员的足够重视。我无法轻易找到有关此问题的上游讨论。

不尝试设置图像尺寸的基准示例

只是为了有一个比较点:

基础文件

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

fig, ax = plt.subplots()
print('fig.dpi = {}'.format(fig.dpi))
print('fig.get_size_inches() = ' + str(fig.get_size_inches())
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig('base.png', format='png')

跑步:

./base.py
identify base.png

输出:

fig.dpi = 100.0
fig.get_size_inches() = [6.4 4.8]
base.png PNG 640x480 640x480+0+0 8-bit sRGB 13064B 0.000u 0:00.000

在此处输入图片描述

我目前最好的方法:plt.savefig(dpi=h/fig.get_size_inches()[1]仅控制高度

我想大多数时候我都会选择这个,因为它简单而且可扩展:

获取大小.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size.png',
    format='png',
    dpi=height/fig.get_size_inches()[1]
)

跑步:

./get_size.py 431

输出:

get_size.png PNG 574x431 574x431+0+0 8-bit sRGB 10058B 0.000u 0:00.000

在此处输入图片描述

./get_size.py 1293

输出:

main.png PNG 1724x1293 1724x1293+0+0 8-bit sRGB 46709B 0.000u 0:00.000

在此处输入图片描述

我倾向于只设置高度,因为我通常最关心图像在文本中间占用多少垂直空间。

plt.savefig(bbox_inches='tight'改变图像大小

我总是觉得图像周围的空白太多,并且倾向于添加bbox_inches='tight'
删除已保存图像周围的空白

但是,这种方法需要裁剪图像,并且无法获得所需的尺寸。

相反,同一问题中提出的另一种方法似乎效果很好:

plt.tight_layout(pad=1)
plt.savefig(...

当高度等于 431 时,它给出了精确的所需高度:

在此处输入图片描述

固定高度、set_aspect自动调整宽度和小边距

呃,set_aspect又把事情搞乱了,并阻止plt.tight_layout真正消除边缘......这是一个重要的用例,我还没有很好的解决方案。

询问:如何在 Matplotlib 中获取固定的像素高度、固定的数据 x/y 纵横比并自动删除水平空白边距?

plt.savefig(dpi=h/fig.get_size_inches()[1]+ 宽度控制

如果除了高度之外您确实需要特定的宽度,那么这似乎可以正常工作:

宽度.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

h = int(sys.argv[1])
w = int(sys.argv[2])
fig, ax = plt.subplots()
wi, hi = fig.get_size_inches()
fig.set_size_inches(hi*(w/h), hi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'width.png',
    format='png',
    dpi=h/hi
)

跑步:

./width.py 431 869

输出:

width.png PNG 869x431 869x431+0+0 8-bit sRGB 10965B 0.000u 0:00.000

在此处输入图片描述

对于较小的宽度:

./width.py 431 869

输出:

width.png PNG 211x431 211x431+0+0 8-bit sRGB 6949B 0.000u 0:00.000

在此处输入图片描述

因此看起来字体的缩放比例确实正确,我们只是遇到了一些麻烦,因为宽度非常小,标签被切断,例如100左上角的标签。

我设法解决了这些问题,删除了已保存图像周围的空白

plt.tight_layout(pad=1)

其结果为:

width.png PNG 211x431 211x431+0+0 8-bit sRGB 7134B 0.000u 0:00.000

在此处输入图片描述

由此,我们还看到,它tight_layout删除了图像顶部的很多空白空间,所以我通常总是使用它。

修复魔法基座高度、dpi开启fig.set_size_inchesplt.savefig(dpi=缩放

我认为这相当于提到的方法: https: //stackoverflow.com/a/13714720/895245

魔法.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

magic_height = 300
w = int(sys.argv[1])
h = int(sys.argv[2])
dpi = 80
fig, ax = plt.subplots(dpi=dpi)
fig.set_size_inches(magic_height*w/(h*dpi), magic_height/dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'magic.png',
    format='png',
    dpi=h/magic_height*dpi,
)

跑步:

./magic.py 431 231

输出:

magic.png PNG 431x231 431x231+0+0 8-bit sRGB 7923B 0.000u 0:00.000

在此处输入图片描述

看看它是否可以很好地扩展:

./magic.py 1291 693

输出:

magic.png PNG 1291x693 1291x693+0+0 8-bit sRGB 25013B 0.000u 0:00.000

在此处输入图片描述

所以我们看到这种方法也确实有效。我遇到的唯一问题是你必须设置该magic_height参数或等效参数。

固定 DPI +set_size_inches

这种方法产生的像素大小略有错误,并且很难无缝缩放所有内容。

设置尺寸英寸.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

w = int(sys.argv[1])
h = int(sys.argv[2])
fig, ax = plt.subplots()
fig.set_size_inches(w/fig.dpi, h/fig.dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(
    0,
    60.,
    'Hello',
    # Keep font size fixed independently of DPI.
    # https://stackoverflow.com/questions/39395616/matplotlib-change-figsize-but-keep-fontsize-constant
    fontdict=dict(size=10*h/fig.dpi),
)
plt.savefig(
    'set_size_inches.png',
    format='png',
)

跑步:

./set_size_inches.py 431 231

输出:

set_size_inches.png PNG 430x231 430x231+0+0 8-bit sRGB 8078B 0.000u 0:00.000

因此高度稍微偏离,图像:

在此处输入图片描述

如果我将其放大 3 倍,像素大小也是正确的:

./set_size_inches.py 1291 693

输出:

set_size_inches.png PNG 1291x693 1291x693+0+0 8-bit sRGB 19798B 0.000u 0:00.000

在此处输入图片描述

然而,我们从中了解到,为了使这种方法很好地扩展,您需要使每个 DPI 相关的设置与英寸尺寸成比例。

在上例中,我们仅将“Hello”文本按比例缩放,并且其高度确实保持在 60 到 80 之间,正如我们预期的那样。但是,如果我们没有这样做,所有内容看起来都很小,包括:

  • 轴线宽度

  • 勾选标签

  • 点标记

SVG

我找不到如何为 SVG 图像设置它,我的方法仅适用于 PNG,例如:

获取_size_svg.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size_svg.svg',
    format='svg',
    dpi=height/fig.get_size_inches()[1]
)

跑步:

./get_size_svg.py 431

生成的输出包含:

<svg height="345.6pt" version="1.1" viewBox="0 0 460.8 345.6" width="460.8pt"

并识别说:

get_size_svg.svg SVG 614x461 614x461+0+0 8-bit sRGB 17094B 0.000u 0:00.000

如果我在 Chromium 86 中打开它,浏览器调试工具鼠标图像悬停时确认高度为 460.79。

但当然,由于 SVG 是一种矢量格式,理论上一切都应该缩放,因此您可以转换为任何固定大小的格式而不会损失分辨率,例如:

inkscape -h 431 get_size_svg.svg -b FFF -e get_size_svg.png

给出精确的高度:

在此处输入图片描述

我在这里使用Inkscape而不是ImageMagick ,因为您也convert需要使用ImageMagick 来获得清晰的 SVG 调整大小:-density

HTML 上的设置<img height=""也应该适用于浏览器。

它在 matplotlib 3.2.2 上进行了测试。

解决方案 11:

概括并简化psihodelia 的答案:

如果你想通过一个因子改变图形的当前尺寸sizefactor

import matplotlib.pyplot as plt

# Here goes your code

fig_size = plt.gcf().get_size_inches() # Get current size
sizefactor = 0.8 # Set a zoom factor
# Modify the current size by the factor
plt.gcf().set_size_inches(sizefactor * fig_size) 

更改当前大小后,可能需要微调子图布局。您可以在图形窗口 GUI 中执行此操作,也可以通过命令subplots_adjust

例如,

plt.subplots_adjust(left=0.16, bottom=0.19, top=0.82)

解决方案 12:

即使在图形绘制完成后,也会立即调整图形大小(至少使用 Qt4Agg/TkAgg - 但不使用 Mac OS X - 带有 Matplotlib 1.4.0):

matplotlib.pyplot.get_current_fig_manager().resize(width_px, height_px)

解决方案 13:

我通常更关心高度/宽度的相对大小,而不是英寸的实际值。因此,我使用它plt.figaspect()来设置纵横比。

# Make the image 3x as wide as it is tall
fix, ax = plt.subplots(figsize=plt.figaspect(1/3))
plt.title("I'm 3x as wide as I am tall")
plt.show()

在此处输入图片描述

解决方案 14:

我总是使用以下模式:

x_inches = 150*(1/25.4)     # [mm]*constant
y_inches = x_inches*(0.8)
dpi = 96

fig = plt.figure(1, figsize = (x_inches,y_inches), dpi = dpi, constrained_layout = True)

在本例中,您可以设置图形尺寸(英寸或毫米)。设置constrained_layout为时True,绘图将填充图形,无边框。

解决方案 15:

您还可以在与 一起使用的自定义样式表中设置图形的默认大小matplotlib.style.use。在您的.mplstyle文件中,包含一行设置rcParams['figure.figsize']

figure.figsize : 8, 6

数字之间的空格是可选的,您可以使用整数或浮点数。

然后,use在创建图之前调用,例如,如果您的样式文件my_style_file.mplstyle位于同一目录中:

matplotlib.style.use('my_style_file.mplstyle')

样式文件中的数字(86我的示例中)相当于您在figsize参数中提供的数字:plt.figure(... figsize = (8,6) ...),但其行为类似于rcParams['figure.figsize']在文件开头设置,即每个新图形都将是该大小,而无需在每个新图形中指定大小。

解决方案 16:

TL;DR:更改 dpi

如果您想要缩放图形而不改变其中每个元素的大小,这尤其有用。有两种方法可以设置 dpi:(a) 通过参数将其传递给图形构造dpi=函数,或 (b)set_dpi在图形实例上调用。以下显示了如何设置dpi=50

data = [3, 5, 1, 7, 6, 7, 2]

# case 1a
plt.figure(dpi=50)
plt.plot(data)

# case 1b
fig, ax = plt.subplots(dpi=50)
ax.plot(data)

# case #2
plt.plot(data)
plt.gcf().set_dpi(50)

下图显示了 dpi 如何影响图形大小。请注意,两个图形的 figsize 相同。

结果

如果您的图表是由第三方库(例如 pandas 或 seaborn)生成的,那么您可以使用.figureAxes 对象访问图形实例并更改其 dpi。

# pandas example
s = pd.Series([3, 5, 1, 7, 6, 7, 2])
ax = s.plot()
ax.figure.set_dpi(72)   # <--- change dpi via Axes

# seaborn example
ax = sns.lineplot(s)
ax.figure.set_dpi(72)   # <--- change dpi via Axes

它是如何工作的?

每个 matplotlib 元素的大小由三个属性的相互作用决定:

  1. 英寸尺寸:通过:获取当前尺寸fig.get_size_inches()并通过 进行更改fig.set_size_inches()。默认尺寸为 (6.4, 4.8)。

  2. dpi(每英寸点数/像素数):通过获取当前 dpi:fig.get_dpi()并通过更改它fig.set_dpi()。默认 dpi 为 100。使用默认设置的图形使用 307,200 像素(=6.4x100x4.8x100)绘制。通过更改像素数,我们可以更改图形的大小(以及图形上绘制的所有内容,例如线条、标记、刻度标签、边框、标签、标题等)。

  3. ppi(每英寸点数):固定为 ppi=72。点是 matplotlib 元素大小(线宽、标记大小、字体大小等)的单位。例如,一条线的lw=1宽度为 1/72 英寸,一个字母的fontsize=10高度为 10/72 英寸等。如果dpi=100lw=1一条线的宽度为 100/72 像素,一个字母的fontsize=10高度为 1000/72 像素等。

假设我们有一个图形,其中figsize=(4,2)dpi=100。如果我们将图形宽度从 4 减小到 2,那么像素变化量为 400 到 200。但是,由于 ppi 是常数,因此绘图上所有东西的大小保持不变,即lw=1线条宽度仍为 1/72 英寸(100/72 像素),即使其绘制的图形现在宽度为 200 像素。从视觉上看,绘图上的所有内容相对于图形大小看起来都会更大/更粗。

另一方面,如果我们降低 dpi,则所有内容都会按比例变小。如果我们将 dpi 从 100 降低到 50,则图宽会从 400 像素变为 200 像素,lw=1线宽会从 100/72 像素变为 50/72 像素,等等,换句话说,每个元素的像素大小都会减半。

比较


生成上述图形所用的代码:

for figsize, dpi in [((4,2), 100), ((4,2), 50), ((2,1), 100)]:
    plt.figure(figsize=figsize, dpi=dpi)
    plt.plot([3,5,1,7,6,7,2])
    plt.title(f"figsize={figsize}, dpi={dpi}")
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用