使用滑块 set_array() 在 matplotlib 图上设置颜色

Set colors on matplotlib plot with slider, set_array()

我有一个带有滑块的 matplotlib 图,我有兴趣设置当滑块以一种或另一种方式被拖动时绘制的点的颜色。我知道您可以使用 set_array() 设置点的颜色,但到目前为止,只有 set_array() 一维浮点数组是幸运的。当我传递 set_array() 一个对应于 matplotlib 颜色的字符串数组时,我收到下面的错误和回溯。

这里有一些相关的代码片段,带有虚拟信息。为了便于评估。 update(val) 中的两行被注释掉,出现以下错误。取消注释它们,以便 set_array() 得到一个浮动,解决了这个问题,但后来我失去了精确控制颜色的能力。 (例如,将 'g' 更改为 'c' 不会在颜色上产生明显的差异。)

import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import matplotlib.colors as c

x = np.linspace(1, 100, 100)
y = x**2

fig, ax = plt.subplots()
plt.subplots_adjust(left=0.1, bottom=0.20)

plt.ylim([y.min(), y.max()])
plt.xlim([0, 100])

init = 4

scat = ax.scatter(x[:init], y[:init], s=5, c=['k']*init)
ax_slider = plt.axes([0.15, 0.05, 0.65, 0.03])
slider = Slider(ax_slider, 'Day', 0, 100, valinit=init, valfmt="%i")

#  Update function, called upon slider movement

def update(val):
    val = int(val)

    colors_new = np.array(['k']*val, dtype=object)
    colors_new[::2] = 'g'
    colors_new[1::2] = 'm'
    # colors_new = map(lambda x: c.to_rgb(x), colors_new) 
    # colors_new = np.dot(colors_new, [0.2989, 0.5870, 0.1140])
    scat.set_array(colors_new)

    xx = np.vstack((x[:val], y[:val]))
    scat.set_offsets(xx.T)


#  Call update function on slider value change
slider.on_changed(update)

plt.show()

回溯:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
    return self.func(*args)
  File "/usr/local/Cellar/python/2.7.6_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 531, in callit
    func(*args)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/backends/_backend_tk.py", line 310, in idle_draw
    self.draw()
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 12, in draw
    super(FigureCanvasTkAgg, self).draw()
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 437, in draw
    self.figure.draw(self.renderer)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/figure.py", line 1493, in draw
    renderer, self, artists, self.suppressComposite)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/image.py", line 141, in _draw_list_compositing_images
    a.draw(renderer)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 2635, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/image.py", line 141, in _draw_list_compositing_images
    a.draw(renderer)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/collections.py", line 911, in draw
    Collection.draw(self, renderer)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/artist.py", line 55, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/collections.py", line 264, in draw
    self.update_scalarmappable()
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/collections.py", line 808, in update_scalarmappable
    self._facecolors = self.to_rgba(self._A, self._alpha)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/cm.py", line 274, in to_rgba
    x = self.norm(x)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/colors.py", line 943, in __call__
    self.autoscale_None(result)
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/matplotlib/colors.py", line 994, in autoscale_None
    self.vmin = A.min()
  File "/Users/johnsmith/PycharmProjects/LawSchoolData/venv/lib/python2.7/site-packages/numpy/ma/core.py", line 5602, in min
    axis=axis, out=out, **kwargs).view(type(self))
AttributeError: 'str' object has no attribute 'view'

set_array() 仅在颜色由颜色图定义时用于设置颜色值。您可以创建自定义 ListedColormap 并设置数值。

如果你想通过颜色值设置颜色,你可以使用set_facecolors():

import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

x = np.linspace(1, 100, 100)
y = x**2

fig, ax = plt.subplots()
plt.subplots_adjust(left=0.1, bottom=0.20)

plt.ylim([y.min(), y.max()])
plt.xlim([0, 100])

init = 4

scat = ax.scatter(x[:init], y[:init], s=5, c=['k']*init)
ax_slider = plt.axes([0.15, 0.05, 0.65, 0.03])
slider = Slider(ax_slider, 'Day', 0, 100, valinit=init, valfmt="%i")

#  Update function, called upon slider movement
def update(val):
    val = int(val)

    colors_new = np.array(['k']*val, dtype=object)
    colors_new[::2] = 'g'
    colors_new[1::2] = 'm'
    scat.set_facecolors(colors_new)

    xx = np.vstack((x[:val], y[:val]))
    scat.set_offsets(xx.T)

#  Call update function on slider value change
slider.on_changed(update)

plt.show()

这是一个使用颜色图的示例:

colors = ['k', 'g', 'm']
cmap = ListedColormap(colors)
scat = ax.scatter(x[:init], y[:init], s=5, c=np.zeros(init), cmap=cmap, vmin=0, vmax=len(colors)-1)

#....

def update(val):
    val = int(val)

    colors_new = np.zeros(val)
    colors_new[::2] = 1
    colors_new[1::2] = 2
    scat.set_array(colors_new)
    #....