问题:有没有办法检查颜色条是否已经存在?
我正在制作许多带有循环的情节.问题是每次迭代都会绘制颜色条!
如果我可以确定颜色条是否存在,那么我可以将颜色条功能放在if语句中.
if cb_exists: # do nothing else: plt.colorbar() #draw the colorbar
如果我使用多处理来制作数字,是否可以防止添加多个颜色条?
import numpy as np import matplotlib.pyplot as plt import multiprocessing def plot(number): a = np.random.random([5,5])*number plt.pcolormesh(a) plt.colorbar() plt.savefig('this_'+str(number)) # I want to make a 50 plots some_list = range(0,50) num_proc = 5 p = multiprocessing.Pool(num_proc) temps = p.map(plot,some_list)
我知道在绘制下一次迭代之前我可以用plt.clf()和plt.cla()清除这个图.但是,我在我的底图图层上有数据我不想重新绘制(这会增加创建绘图所需的时间).所以,如果我可以删除颜色条并添加一个新颜色,我会节省一些时间.
解决方法
实际上不容易从绘图中删除颜色条,然后再绘制一个新颜色.
我现在能想出的最佳解决方案如下,假设图中只有一个轴.现在,如果有第二个轴,它必须是存在的颜色条.因此,通过检查我们在图上找到多少轴,我们可以判断是否存在颜色条.
我现在能想出的最佳解决方案如下,假设图中只有一个轴.现在,如果有第二个轴,它必须是存在的颜色条.因此,通过检查我们在图上找到多少轴,我们可以判断是否存在颜色条.
在这里,我们还要注意用户不希望从外部引用任何命名对象. (这没有多大意义,因为我们无论如何都需要使用plt,但是嘿..问题也是如此)
import matplotlib.pyplot as plt import numpy as np fig,ax = plt.subplots() im = ax.pcolormesh(np.array(np.random.rand(2,2) )) ax.plot(np.cos(np.linspace(0.2,1.8))+0.9,np.sin(np.linspace(0.2,c="k",lw=6) ax.set_title("Title") cbar = plt.colorbar(im) cbar.ax.set_ylabel("Label") for i in range(10): # inside this loop we should not access any variables defined outside # why? no real reason,but questioner asked for it. #draw new colormesh im = plt.gcf().gca().pcolormesh(np.random.rand(2,2)) #check if there is more than one axes if len(plt.gcf().axes) > 1: # if so,then the last axes must be the colorbar. # we get its extent pts = plt.gcf().axes[-1].get_position().get_points() # and its label label = plt.gcf().axes[-1].get_ylabel() # and then remove the axes plt.gcf().axes[-1].remove() # then we draw a new axes a the extents of the old one cax= plt.gcf().add_axes([pts[0][0],pts[0][1],pts[1][0]-pts[0][0],pts[1][1]-pts[0][1] ]) # and add a colorbar to it cbar = plt.colorbar(im,cax=cax) cbar.ax.set_ylabel(label) # unfortunately the aspect is different between the initial call to colorbar # without cax argument. Try to reset it (but still it's somehow different) cbar.ax.set_aspect(20) else: plt.colorbar(im) plt.show()
通常,更好的解决方案是对绘图中已存在的对象进行操作,并仅使用新数据更新它们.因此,我们无需移除和添加轴,并找到更清洁,更快速的解决方案.
import matplotlib.pyplot as plt import numpy as np fig,lw=6) ax.set_title("Title") cbar = plt.colorbar(im) cbar.ax.set_ylabel("Label") for i in range(10): data = np.array(np.random.rand(2,2) ) im.set_array(data.flatten()) cbar.set_clim(vmin=data.min(),vmax=data.max()) cbar.draw_all() plt.draw() plt.show()
更新:
实际上,后一种从外部引用对象的方法甚至与提问者所希望的多进程方法一起工作.
import matplotlib.pyplot as plt import numpy as np import multiprocessing import time fig,c="w",lw=6) ax.set_title("Title") cbar = plt.colorbar(im) cbar.ax.set_ylabel("Label") tx = ax.text(0.2,0.8,"",fontsize=30,color="w") tx2 = ax.text(0.2,0.2,color="w") def do(number): start = time.time() tx.set_text(str(number)) data = np.array(np.random.rand(2,2)*(number+1) ) im.set_array(data.flatten()) cbar.set_clim(vmin=data.min(),vmax=data.max()) tx2.set_text("{m:.2f} < {ma:.2f}".format(m=data.min(),ma= data.max() )) cbar.draw_all() plt.draw() plt.savefig("multiproc/{n}.png".format(n=number)) stop = time.time() return np.array([number,start,stop]) if __name__ == "__main__": multiprocessing.freeze_support() some_list = range(0,50) num_proc = 5 p = multiprocessing.Pool(num_proc) nu = p.map(do,some_list) nu = np.array(nu) plt.close("all") fig,ax = plt.subplots(figsize=(16,9)) ax.barh(nu[:,0],nu[:,2]-nu[:,1],height=np.ones(len(some_list)),left=nu[:,align="center") plt.show()