Matplotlib生成的PDF更大且模糊,能否优化至R生成的水平?
问题:Matplotlib生成PDF质量及体积优化方案
用户分别用R和Matplotlib绘制相同数据的直方图并保存为PDF,代码如下:
R代码
set.seed(42) x = c(rnorm(1000, 1, 1), rnorm(1000, 8, 3)) pdf("Rplot.pdf", width = 10, height = 3.33) par(mar = c(4, 5, 0, 0), family = "serif") hist(x, breaks = 100, border = NA, col = "gray", xlab = "x", ylab = "Frequency", cex.lab = 2.75, cex.axis = 2, main = "", las = 1, xaxt = "n") axis(side = 1, at = seq(-2.5, by = 2.5, len = 30), cex.axis = 2) dev.off()
Matplotlib原始代码
import numpy as np import matplotlib.pyplot as plt np.random.seed(42) x = np.concatenate((np.random.normal(1, 1, size = 1000), np.random.normal(8, 3, size = 1000))) plt.close() plt.rcParams["figure.figsize"] = (10, 3.33) plt.rcParams["font.family"] = "Times New Roman" plt.rcParams["axes.spines.bottom"] = True plt.rcParams["axes.spines.left"] = True plt.rcParams["axes.spines.top"] = False plt.rcParams["axes.spines.right"] = False tmp = plt.hist(x, bins = 100, color = 'lightgray') plt.xlabel('x', fontsize = 30) plt.ylabel('Frequency', fontsize = 30) tmp = plt.xticks(fontsize = 25) tmp = plt.yticks(fontsize = 25) plt.tight_layout() plt.savefig("pyPlot.pdf", bbox_inches='tight')
现象
生成的pyPlot.pdf(13KB)体积是Rplot.pdf(5KB)的2.6倍,且在Adobe Reader中显示更模糊;但保存为SVG格式时两者效果一致。用户希望用Matplotlib生成与R版本同等质量和体积的PDF,同时想了解R是否有额外优化。
解决方案
关键差异说明
R的PDF设备默认使用Type 1矢量字体,且对图形元素的矢量渲染做了精简;而Matplotlib默认使用Type 3字体(位图化矢量字体),且直方图绘制时可能生成冗余的矢量路径,导致文件体积大、显示模糊。
优化后的Matplotlib代码如下:
import numpy as np import matplotlib.pyplot as plt np.random.seed(42) x = np.concatenate((np.random.normal(1, 1, size=1000), np.random.normal(8, 3, size=1000))) plt.close() # 核心优化:强制使用Type 1矢量字体,避免位图化模糊 plt.rcParams["pdf.fonttype"] = 42 plt.rcParams["ps.fonttype"] = 42 plt.rcParams["figure.figsize"] = (10, 3.33) plt.rcParams["font.family"] = "serif" # 和R的family="serif"保持一致 plt.rcParams["axes.spines.bottom"] = True plt.rcParams["axes.spines.left"] = True plt.rcParams["axes.spines.top"] = False plt.rcParams["axes.spines.right"] = False # 绘制直方图时关闭边缘,减少冗余矢量元素 n, bins, patches = plt.hist(x, bins=100, color='gray', edgecolor='none') plt.xlabel('x', fontsize=30) plt.ylabel('Frequency', fontsize=30) # 对齐R的坐标轴刻度逻辑 plt.xticks(ticks=np.arange(-2.5, 70, 2.5), fontsize=25) plt.yticks(fontsize=25) plt.tight_layout() # 优化保存参数,压缩文件体积同时保证精度 plt.savefig("pyPlot_optimized.pdf", bbox_inches='tight', dpi=600, facecolor='white', edgecolor='none') plt.close()
优化点详解
- 字体设置:
pdf.fonttype=42和ps.fonttype=42强制使用Type 1矢量字体,彻底解决模糊问题并显著缩小文件体积。 - 图形精简:直方图设置
edgecolor='none'(对应R的border=NA),避免生成大量冗余的边缘路径。 - 样式对齐:统一字体家族、坐标轴刻度逻辑,保证和R生成的图形样式一致。
- 保存优化:
dpi=600保证矢量渲染精度,配合默认的PDF压缩机制进一步缩小体积。
效果验证
优化后的PDF体积会接近R生成的版本,显示清晰度完全一致,SVG格式效果也不受影响。
内容的提问来源于stack exchange,提问作者user2961927
相关产品推荐
相关产品推荐

