当参数改变时如何自动更改颜色

4
在下面的代码中,当阈值改变时,条形的颜色也会改变。我想要在OnMouseMove函数中使用y参数来代替代码中的阈值并绘制水平线,以便用户可以更改“阈值”的位置。然后,当y改变时,我希望颜色得到更新。
我认为我需要的是所谓的“观察者模式”,或者可能是一种使用动画工具的技巧,但不确定如何实现。感谢任何关于如何做到这一点的见解。谢谢。
%matplotlib notebook
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.colors as mcol
import matplotlib.cm as cm
import matplotlib.pyplot as plt

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(335,1500,300), 
                   np.random.normal(410,900,300), 
                   np.random.normal(410,1200,300), 
                   np.random.normal(480,550,300)], 
                  index=[1,2,3,4])

fig, ax = plt.subplots()
plt.show()
bars = plt.bar(range(df.shape[0]), df.mean(axis = 1), color = 'lightslategrey')

fig = plt.gcf()
threshold=420
plt.axhline(y = threshold, color = 'grey', alpha = 0.5)

cm1 = mcol.LinearSegmentedColormap.from_list("Test",["b", "white", "purple"])
cpick = cm.ScalarMappable(cmap=cm1)
cpick.set_array([])

percentages = []
for bar in bars:
    percentage = (bar.get_height()-threshold)/bar.get_height()
    if percentage>1: percentage = 1
    if percentage<0: percentage=0
    percentages.append(percentage)

cpick.to_rgba(percentages)
bars = plt.bar(range(df.shape[0]), df.mean(axis = 1), color = cpick.to_rgba(percentages))
plt.colorbar(cpick, orientation='horizontal')

def onMouseMove(event):
    ax.lines = [ax.lines[0]]
    plt.axhline(y=event.ydata, color="k")

fig.canvas.mpl_connect('motion_notify_event', onMouseMove)

plt.xticks(range(df.shape[0]), df.index, alpha = 0.8)

year_avg的值是多少? - eyllanesc
df.mean(axis=1)。谢谢,刚才有误,已经更正。 - user3709260
1个回答

6

首先,您应该只使用一个条形图和一条axhline(使用更多会使一切混乱)。您可以通过以下方式设置条的颜色:

for bar in bars:
    bar.set_color(..)

你可以通过line.set_ydata(position)更新axhline的位置。

现在,对于每个鼠标移动事件,您需要更新axhline的位置,计算百分比并将新颜色应用于条形图。因此,这些操作应该在一个函数中完成,在每次触发鼠标移动事件时调用。应用这些设置后,需要绘制画布才能使它们变得可见。

下面是完整的代码。

import pandas as pd
import numpy as np
import matplotlib.colors as mcol
import matplotlib.cm as cm
import matplotlib.pyplot as plt

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(335,1500,300), 
                   np.random.normal(410,900,300), 
                   np.random.normal(410,1200,300), 
                   np.random.normal(480,550,300)], 
                  index=[1,2,3,4])

fig, ax = plt.subplots()

threshold=420.
bars = plt.bar(range(df.shape[0]), df.mean(axis = 1), color = 'lightslategrey')
axline = plt.axhline(y = threshold, color = 'grey', alpha = 0.5)

cm1 = mcol.LinearSegmentedColormap.from_list("Test",["b", "white", "purple"])
cpick = cm.ScalarMappable(cmap=cm1) 
cpick.set_array([])
plt.colorbar(cpick, orientation='horizontal')

def percentages(threshold):
    percentages = []
    for bar in bars:
        percentage = (bar.get_height()-threshold)/bar.get_height()
        if percentage>1: percentage = 1
        if percentage<0: percentage=0
        percentages.append(percentage)
    return percentages

def update(threshold):
    axline.set_ydata(threshold)
    perc = percentages(threshold)
    for bar, p in zip(bars, perc):
        bar.set_color(cpick.to_rgba(p))

# update once before showing
update(threshold)

def onMouseMove(event):
    if event.inaxes == ax:
        update(event.ydata)
        fig.canvas.draw_idle()

fig.canvas.mpl_connect('motion_notify_event', onMouseMove)

plt.xticks(range(df.shape[0]), df.index, alpha = 0.8)

plt.show()

2
请注意,如果您想在Jupyter笔记本中使用此代码,则需要使用交互式后端“%matplotlib notebook”。 - Sos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接