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

时间:2017-12-18 04:24:59

标签: pdf matplotlib seaborn

尝试将一些实验数据保存到文件中我注意到在尝试保存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甚至没有发生。 这是正常的吗?以及如何解决它

谢谢!

1 个答案:

答案 0 :(得分: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保存png需要更长时间(此处最多N=30或{{1 }})。但是图中的瓷砖越多,需要在pdf中存储的形状越多,因此最终需要更长的时间来保存pdf格式的许多瓷砖。我们假设保存pdf文件所花费的时间大致与要存储的磁贴数量成比例。这表明时间与NxN = 900N的二次关系。将二次多项式拟合到数据并在time ~ N**2处评估多项式给出

t=1000

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

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