33

这应该很容易,但我很难做到。基本上,我在 matplotlib 中有一个子图,每次调用函数时我都会绘制一个 hexbin 图,但是每次调用该函数时,我都会得到一个新的颜色条,所以我真正想做的是更新颜色条. 不幸的是,这似乎不起作用,因为颜色条附加到的对象正在由 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)

有没有人有什么建议?

非常感激!亚当

4

10 回答 10

30

我认为问题在于del您取消了变量,而不是引用的对象颜色条。如果要从绘图中删除颜色条并消失,则必须使用remove颜色条实例的方法,为此,您需要将颜色条放在变量中,对此您有两种选择:

  1. 在创建时将颜色条保持在一个值中,如其他答案所示,例如cb=plt.colorbar()
  2. 检索现有的颜色条,您可以按照我在此处写的内容进行操作(并支持 :)):如何从 matplotlib 中的图形中检索颜色条实例 然后:

cb.remove() plt.draw() #update plot


完整代码和结果:

from matplotlib import pyplot as plt 
import numpy as np

plt.ion() 
plt.imshow(np.random.random(15).reshape((5,3))) 
cb = plt.colorbar() 
plt.savefig('test01.png') 
cb.remove() 
plt.savefig('test02.png')

测试01.png test02.png

于 2015-12-04T02:32:24.230 回答
12

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

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)

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

于 2011-03-10T20:37:14.980 回答
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)
于 2015-11-25T11:38:48.433 回答
3

我有一个类似的问题,并玩了一点。我想出了两个可能更优雅的解决方案:

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

  2. 如果总是有一个颜色条,您可以简单地使用自动缩放更新轴,这也会更新颜色条。

我已经用 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()
于 2013-05-27T14:23:59.697 回答
3

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

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

伪代码:

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

   cb.remove()
   p.remove()

同样,有必要在 pcolormesh 之前删除颜色条

于 2016-10-06T20:54:08.443 回答
3

如果你有一个 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)

在此处输入图像描述

删除彩条

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])

在此处输入图像描述

于 2020-02-05T00:21:22.997 回答
1

我正在使用 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只是在旧的颜色条轴上绘制新的颜色条。

于 2014-08-26T04:54:29.027 回答
1

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

总而言之,从命令的轴ax的任何输出:plotimagescattercollection等,例如:

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()

创建的颜色条将具有与图形或子图相同的大小,您可以在使用divider.append_axes命令时修改它的宽度位置填充。

于 2017-11-20T19:29:44.480 回答
0

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

例如,定义一次:

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)

在此处输入图像描述

于 2021-07-20T14:51:10.373 回答
-1

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

if self.cb:
    self.cb.on_mappable_changed(hb)
else:
    self.cb = self.fig.colorbar(hb)
于 2014-11-03T16:07:50.123 回答