将散点图的色条分开保存

4

我有一个带颜色条的散点图,我将其保存为PNG图像。我需要这个图的尺寸符合特定要求,但是添加颜色条会使原始图缩放。

import pylab as plt

plt.figure(figsize=FIGSIZE)
plt.scatter(X, Y, c=Z, s=marker_size, norm=LogNorm(), vmin=VMIN, vmax=VMAX, cmap=CMAP,rasterized=True,lw=0,)
CB = plt.colorbar(ticks=TICKS, format=FORMAT)

我该如何将原始图(大小设置如上)和颜色条保存为两个单独的图像?
1个回答

12
显然的答案是“单独绘制色条”。您需要创建一个新的图形窗口,并在其中绘制您的色条,以防止第一个图形变形。以下是一个小例子:
import matplotlib.pyplot as plt
import numpy as np    # only for dummy data

X,Y = np.mgrid[-2:3,-2:3]
Z = np.random.rand(*X.shape)
FIGSIZE = (2,3)

plt.figure(figsize=FIGSIZE)
mpb = plt.pcolormesh(X,Y,Z,cmap='viridis')
# plot the original without a colorbar
plt.savefig('plot_nocbar.png')

# plot a colorbar into the original to see distortion
plt.colorbar()
plt.savefig('plot_withcbar.png')

# draw a new figure and replot the colorbar there
fig,ax = plt.subplots(figsize=FIGSIZE)
plt.colorbar(mpb,ax=ax)
ax.remove()
plt.savefig('plot_onlycbar.png')

# save the same figure with some approximate autocropping
plt.savefig('plot_onlycbar_tight.png',bbox_inches='tight')

请查看以下四个图表(点击以查看完整版):

no colorbar distorted with colorbar separate colorbar with much white cropped colorbar

第一个图是没有调用colormap的保存版本。这是可以的,这就是你想要保留的。第二个图展示了如果我们不做任何额外的操作调用colorbar会发生什么:它会从原始图中占用一些空间,这是你想要避免的。你需要使用plt.subplots打开一个新的图(和坐标轴),大小与原始图相同。这样你就可以确保产生的色条与在原始图中绘制的大小相同。在上述设置中,我让matplotlib自己确定颜色条的大小;但之后我们需要删除污染结果图的辅助坐标轴。(另一种选择是手动在新图中创建一个坐标轴,其颜色条的期望大小。我怀疑这不是可行的做法。)现在,正如你在第三张图中看到的那样,在删除的坐标轴留下的空白空间在结果图中明显可见(但颜色条的大小是完美的)。你可以在后期手动剪切掉这个白色空间,或者使用一些自动裁剪你的颜色条图像的工具。
我还包括了一个版本的图表,其中 matplotlib 自己裁剪了大部分的图形:使用 bbox_inches='tight' 关键字参数调用 savefig 可以实现这一点。优点是生成的图像文件仅包含色条(如上面第四幅图所示),但生成的色条大小将与您的原始色条略有不同。根据您的具体需求,您需要尝试可用的方法,找到最方便的解决方案。

太棒了!谢谢你!我使用了你上一个例子。 唯一让我无法理解的是,为什么设置dpi和figsize会导致结果图像大小出乎意料(我设置了figsize =(3,8)和dpi = 80,但生成的绘图尺寸为144x660像素,而不是240x640像素)。 - AntonK
1
@AntonK 如果你在调用 figure() 时设置了 dpi=80,它只会影响屏幕上的输出。为了在输出文件中获得预期的 dpi,你需要在调用 plt.savefig("filename.png", dpi=80) 时设置 dpi=80(默认值是100)。此外,使用 bbox_inches='tight' 将改变 figsize(这就是你使用它的原因,对吧?),因此你的输出图像大小是不可预测的。如果你需要特定的输出大小,就不应该调用 bbox_inches='tight' - ImportanceOfBeingErnest
@ImportanceOfBeingErnest 感谢您的建议,我对“dpi”设置完全不熟悉。至于色条,我认为这种调整大小对OP来说是可以的:重要的是图本身具有给定的大小,然后可以在其旁边放置单独的色条(否则问题对我来说似乎没有意义)。在这种情况下,重要的是生成的色条与将绘制的图相对应,这就是为什么我建议从相同大小的图开始(但随后它确实会被裁剪到自动设置的色条大小)。 - Andras Deak -- Слава Україні
@ImportanceOfBeingErnest 很抱歉,我花了一些时间才理解你关于图像大小的观点:) 是的,你也是对的,由于裁剪,结果的长宽比将不会是输入图像的长宽比。但这应该没问题,因为否则 OP 将会在图像中得到额外的腿部空间,或者一个非常丑陋的颜色条。 - Andras Deak -- Слава Україні

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接