Seaborn热图到.pdf非常慢。这是正常的吗?

问题描述 投票:2回答:1

试图将一些实验数据保存到文件中我发现当尝试保存NxN大小的热图时,执行将永远不会完成。进一步调查似乎是由于.pdf扩展名。例如,如果我使用.png,它的速度非常快。

最小可重复的例子:

import matplotlib.pylab as plt
import numpy as np
import seaborn as sbn

N=200
THE_FIGURE = plt.figure(figsize=(8.27, 6), dpi=300)
ax = plt.subplot(1, 1, 1)
sbn.heatmap(np.random.uniform(1, 20, (N, N)), ax=ax)
THE_FIGURE.savefig('image.pdf', bbox_inches='tight', pad_inches=0.1)

即使N = 100,这种减速也变得明显.N = 1000甚至没有发生。这是正常的吗?以及如何解决它

谢谢!

pdf matplotlib seaborn
1个回答
2
投票

有意义的是,对于更大的网格,节省pdf比保存png需要更长的时间。这可以在下图中看到,其中显示了将pdf和png保存为沿一个轴(N)的瓦片数量的函数的时间(实线)。我们还可以查看pdf和png的文件大小,其中有一些类似的行为(虚线)。

enter image description here

在这里找到复制代码。在我的电脑上运行它需要大约1:10分钟。

import matplotlib.pylab as plt
import numpy as np
import seaborn as sns
import time
import os

def f(N, form = "pdf"):
    t0= time.time()
    fig = plt.figure(figsize=(8.27, 6), dpi=300)
    ax = plt.subplot(1, 1, 1)
    sns.heatmap(np.random.uniform(1, 20, (N, N)), ax=ax)
    fig.savefig('image.'+form, bbox_inches='tight', pad_inches=0.1)
    t1 = time.time()
    plt.close(fig)
    s = os.path.getsize('image.'+form)
    return t1-t0,s

ns = [5,10,15,20,25,30] + range(40,210, 20)
pdf = []
png = []

for i,n in enumerate(ns):
    pdf.append(f(n, form="pdf"))
    png.append(f(n, form="png"))
    #print i, n

pdf = np.array(pdf);png = np.array(png)
plt.figure()    
plt.plot(ns, pdf[:,0], label="pdf")
plt.plot(ns, png[:,0], label="png")
plt.xlabel("N")
plt.ylabel("time [s]")
ax2 = plt.gca().twinx()
ax2.plot(ns, pdf[:,1]/1000., label="pdf (filesize)", ls="--")
ax2.plot(ns, png[:,1]/1000., label="png (filesize)", ls="--")
ax2.set_ylabel("filesize [kByte]")
plt.gcf().legend(ncol=2, loc="upper left", bbox_to_anchor=(0.125,0.98))
plt.subplots_adjust(top=0.85)
plt.show()

原因似乎也很直观。 Png是位图格式,它将图像保存为像素。 Pdf是一种矢量格式,它将图像保存为矢量形状。

虽然png需要存储相同数量的像素(在这种情况下约为2000x1500),但是为小N(这里高达N=30NxN = 900)保存png需要更长的时间。但是图中的瓷砖越多,需要在pdf中存储的形状越多,因此最终需要更长的时间来保存pdf格式的许多瓷砖。我们假设保存pdf文件所花费的时间大致与要存储的磁贴数量成比例。这表明时间与Ntime ~ N**2有二次关系。将二次多项式拟合到数据并在t=1000处评估多项式给出

fit = np.polyfit(ns, pdf[:,0], 2)
print( np.poly1d(fit)(1000) )

给出340秒,即5:40分钟。这是保存1000x1000矩阵所需的估计时间。

注意:此处的所有数据均在运行python 2.7和matplotlib 2.1的Intel i5 3.5GHz Windows计算机上生成。使用不同的计算机当然会改变时间。

© www.soinside.com 2019 - 2024. All rights reserved.