从matplotlib中的数字中删除colorbar

时间:2011-03-10 16:55:04

标签: python matplotlib colorbar

这应该很容易,但我很难用它。基本上,我在matplotlib中有一个子图,我在每次调用函数时都会绘制一个hexbin图,但每次调用该函数时我都会得到一个新的颜色条,所以我真正想做的就是更新colorbar 。不幸的是,这似乎不起作用,因为colorbar附加的对象正在由subplot.hexbin重新创建。

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.cb.update_bruteforce() # Doesn't work (hb is new)
   else:
      self.cb = self.figure.colorbar(hb)

我现在正处于这个烦人的地方,我试图完全删除颜色条轴并简单地重新创建它。不幸的是,当我删除颜色条轴时,子图轴不会回收空间,调用self.subplot.reset_position()并没有按照我的想法进行。

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.figure.delaxes(self.figure.axes[1])
      del self.cb
      # TODO: resize self.subplot so it fills the 
      #    whole figure before adding the new colorbar
   self.cb = self.figure.colorbar(hb)

有人有任何建议吗?

非常感谢! 亚当

10 个答案:

答案 0 :(得分:20)

我认为问题在于,使用del取消变量,而不是引用的对象颜色条。 如果您希望从绘图中删除颜色条并消失,则必须使用颜色条实例的方法remove并执行此操作,您需要在变量中使用颜色条,您有两个选项: / p>

  1. 在创建时将颜色条保持在一个值中,如其他答案所示,例如: cb=plt.colorbar()
  2. 检索现有的颜色栏,您可以执行以下操作(以及upvoting :))我在此处写的内容:How to retrieve colorbar instance from figure in matplotlib 然后:
  3. cb.remove() plt.draw() #update plot

答案 1 :(得分:9)

好的,这是我的解决方案。不是非常优雅,但也不是一个可怕的黑客。

def foo(self):
   self.subplot.clear()
   hb = self.subplot.hexbin(...)
   if self.cb:
      self.figure.delaxes(self.figure.axes[1])
      self.figure.subplots_adjust(right=0.90)  #default right padding
   self.cb = self.figure.colorbar(hb)

这符合我的需求,因为我只有一个子图。在使用多个子图或在不同位置绘制颜色条时遇到同样问题的人需要进行调整。

答案 2 :(得分:4)

我设法使用fig.clear()和display.clear_output()

解决了同样的问题
import matplotlib.pyplot as plt
import IPython.display as display
import matplotlib.tri as tri
from pylab import *
%matplotlib inline

def plot_res(fig):
    ax=fig.add_axes([0,0,1,1])
    ax.set_xlabel("x")
    ax.set_ylabel('y')
    plotted=ax.imshow(rand(250, 250))
    ax.set_title("title")
    cbar=fig.colorbar(mappable=plotted)
    display.clear_output(wait=True)
    display.display(plt.gcf())
    fig.clear()

fig=plt.figure()
N=20
for j in range(N):
    plot_res(fig)

答案 3 :(得分:3)

我有类似的问题并且玩了一下。我想出了两个可能稍微优雅的解决方案:

  1. 清除整个数字并再次添加子图(如果需要,还可添加+ colorbar)。

  2. 如果总是有颜色条,您只需使用自动缩放更新轴,这也会更新颜色条。

  3. 我已经尝试使用imshow,但我猜它与其他绘图方法类似。

    from pylab import *
    close('all') #close all figures in memory
    
    #1. Figures for fig.clf method
    fig1 = figure()
    fig2 = figure()
    cbar1=None
    cbar2=None
    data = rand(250, 250)
    
    def makefig(fig,cbar):
      fig.clf()
      ax = fig.add_subplot(111)
      im = ax.imshow(data)
      if cbar:
        cbar=None
      else:
        cbar = fig.colorbar(im)
      return cbar
    
    
    #2. Update method
    fig_update = figure()
    cbar3=None
    data_update = rand(250, 250)
    img=None
    
    def makefig_update(fig,im,cbar,data):
      if im:
        data*=2 #change data, so there is change in output (look at colorbar)
        #im.set_data(data) #use this if you use new array
        im.autoscale()
        #cbar.update_normal(im) #cbar is updated automatically
      else:
        ax = fig.add_subplot(111)
        im = ax.imshow(data)
        cbar=fig.colorbar(im)
      return im,cbar,data
    
    #Execute functions a few times
    for i in range(3):
      print i
      cbar1=makefig(fig1,cbar1)
      cbar2=makefig(fig2,cbar2)
      img,cbar3,data_update=makefig_update(fig_update,img,cbar3,data_update)
    cbar2=makefig(fig2,cbar2)
    
    fig1.show()
    fig2.show()
    fig_update.show()
    

答案 4 :(得分:2)

如果您有matplotlib图形对象,则只需执行fig.delaxes(fig.axes[1])

例如:

带有颜色条的图

import matplotlib.pyplot as plt

# setup some generic data
N = 37
x, y = np.mgrid[:N, :N]
Z = (np.cos(x*0.2) + np.sin(y*0.3))

# mask out the negative and positive values, respectively
Zpos = np.ma.masked_less(Z, 0)
Zneg = np.ma.masked_greater(Z, 0)

fig, ax1 = plt.subplots(figsize=(13, 3), ncols=1)

# plot just the positive data and save the
# color "mappable" object returned by ax1.imshow
pos = ax1.imshow(Zpos, cmap='Blues', interpolation='none')

# add the colorbar using the figure's method,
# telling which mappable we're talking about and
# which axes object it should be near
fig.colorbar(pos, ax=ax1)

enter image description here

删除颜色栏

import matplotlib.pyplot as plt

# setup some generic data
N = 37
x, y = np.mgrid[:N, :N]
Z = (np.cos(x*0.2) + np.sin(y*0.3))

# mask out the negative and positive values, respectively
Zpos = np.ma.masked_less(Z, 0)
Zneg = np.ma.masked_greater(Z, 0)

fig, ax1 = plt.subplots(figsize=(13, 3), ncols=1)

# plot just the positive data and save the
# color "mappable" object returned by ax1.imshow
pos = ax1.imshow(Zpos, cmap='Blues', interpolation='none')

# add the colorbar using the figure's method,
# telling which mappable we're talking about and
# which axes object it should be near
fig.colorbar(pos, ax=ax1)

fig.delaxes(fig.axes[1])

enter image description here

答案 5 :(得分:1)

不想从这个blog post(Joseph Long)的作者那里拿走任何东西,但这显然是我迄今为止找到的最佳解决方案。它包括代码片段,很棒的解释和许多例子。

总结一下,从命令的轴 ax 的任何输出: plot image scatter 集合等,如:

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.add_subplot(1, 1, 1)

data = ax.plot(x,y)
# or
data = ax.scatter(x, y, z)
# or
data = ax.imshow(z)
# or 
data = matplotlib.collection(patches)
ax.add_collection(data)

使用 make_axes_locatable 和绘图的原始轴创建颜色条轴。

from mpl_toolkits.axes_grid1 import make_axes_locatable

# the magical part
divider = make_axes_locatable(ax)
caxis = divider.append_axes("right", size="5%", pad=0.05)
fig.colorbar(data, cax=caxis)

plt.show()

创建的颜色栏与图或子图的大小相同,您可以修改 width location padding 使用 divider.append_axes 命令时。

答案 6 :(得分:0)

我正在使用matplotlib 1.4.0。这就是我解决这个问题的方法:

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

# A contour plot example:
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10.0 * (Z2 - Z1)
#

# first drawing
fig = plt.figure()
ax = fig.add_subplot(111)  # drawing axes
c = ax.contourf(Z)   # contour fill c
cb = fig.colorbar(c)  # colorbar for contour c

# clear first drawimg
ax.clear()  # clear drawing axes
cb.ax.clear()  # clear colorbar axes

# replace with new drawing
# 1. drawing new contour at drawing axes
c_new = ax.contour(Z)  
# 2. create new colorbar for new contour at colorbar axes
cb_new = ax.get_figure().colorbar(c_new, cax=cb.ax) 

plt.show()

上面的代码用颜色条绘制轮廓填充图,清除它并在同一图形上用新的颜色条绘制一个新的等高线图。

通过使用     cb.ax 我能够识别颜色条轴并清除旧的颜色条。 并且指定cax=cb.ax只是在旧的颜色条轴上绘制新的颜色条。

答案 7 :(得分:0)

我需要删除颜色条,因为我正在绘制一个pcolormesh并将颜色条添加到循环中的图形中。每个循环都会创建一个新的颜色条,在十个循环后我会有十个颜色条。那很糟糕。

要删除颜色条,我将pcolormesh和colorbar命名为变量,然后在循环结束时删除每个颜色。在删除pcolormesh之前删除colorbar 非常重要。

Psudo代码:

 for i in range(0,10):
   p = plt.pcolormesh(datastuff[i])
   cb = plt.colorbar(p)
   plt.savefig('name_'+i)

   cb.remove()
   p.remove()

同样,有必要在pcolormesh

之前删除颜色条

答案 8 :(得分:0)

我的解决方案是拥有一个轴,其唯一目的是保持颜色条,并在需要时将其完全清除。

例如,定义一次:

figure, ax = plt.subplots() # All the plotting is done on `ax`.
cax = ax.inset_axes([1.03, 0, 0.1, 1], transform=ax.transAxes) # Colorbar is held by `cax`. 

然后根据需要多次执行此操作:

cax.clear()
colorbar = figure.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
                           ax=ax,
                           cax=cax,
                           **kwargs)

enter image description here

答案 9 :(得分:-1)

“on_mappable_changed”在我的案例中有效。但是,根据文档,方法“通常......不应手动调用。”

if self.cb:
    self.cb.on_mappable_changed(hb)
else:
    self.cb = self.fig.colorbar(hb)