【问题标题】:Matplotlib interactive bar chartMatplotlib 交互式条形图
【发布时间】:2020-09-09 17:37:31
【问题描述】:

我正在尝试探索 matplotlib 中的交互功能,基本上用户通过单击图表来选择一个 y 值,根据用户选择的值,绘制一条水平线。根据那条线,条形图的颜色应该会发生变化(值与平均值相差多远)。

我的程序绘制了用户选择的值,但条形的颜色没有相应改变。单击事件调用我的比较值函数,该函数绘制线条但不改变颜色。我的代码如下,任何帮助将不胜感激

import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
import numpy as np


np.random.seed(12345)

df = pd.DataFrame([np.random.normal(32000,200000,3650), 
                   np.random.normal(43000,100000,3650), 
                   np.random.normal(43500,140000,3650), 
                   np.random.normal(48000,70000,3650)], 
                  index=[1992,1993,1994,1995])
df=df.T
n = len(df)
std = df.std()
means = df.mean() 


ci = (1.96*std/(n**0.5))
cu = list(means + ci)
cl = list(means - ci)
yerror = list(zip(cl , cu))
lab =list(df.columns)
x = np.arange(len(lab))


my_cmap = plt.cm.get_cmap('coolwarm')
norm = mpl.colors.Normalize(vmin=0.,vmax=1.)


def cmp_val(n):
    data_c=list((n - means))
    data_c = [x / max(data_c) for x in data_c]
    for i in range(len(data_c)):
        if data_c[i] > 0:
            my_cmap = plt.cm.get_cmap('Blues')
            colors = my_cmap(norm(data_c[i]))
            bar[i].set_facecolor(colors)
        if data_c[i] < 0:
            my_cmap = plt.cm.get_cmap('Reds')
            colors = my_cmap(norm(data_c[i]*-1))
            bar[i].set_facecolor(colors)
    plt.axhline(y=n, xmin=0, xmax=1, c = 'lightslategray', linestyle = ':')

    return n


plt.figure()
bar=plt.bar(x ,list(means), width=x[1]-x[0], edgecolor='black',  yerr= ci,capsize= 20)
plt.xticks(x, lab)

def onclick(event):
    plt.cla()
    bar=plt.bar(x ,list(means), width=x[1]-x[0], edgecolor='black',  yerr= ci,capsize= 20)
    cmp_val(event.ydata)

    plt.gca().set_title('{}'.format(event.ydata))
    plt.xticks(x, lab)

plt.gcf().canvas.mpl_connect('button_press_event', onclick)

plt.show()

【问题讨论】:

  • onclick()后面加plt.draw()有帮助吗?请参阅matplotlib.org/3.3.1/api/_as_gen/matplotlib.pyplot.draw.html 和那里的链接示例。
  • plt.draw() 修复了一个我没有提到的问题,只有当我选择任何图形按钮平移、缩放时才绘制线条。现在使用 plt.draw() 绘制一条线而不选择这些按钮。
  • bar[i] 是一个(类 'matplotlib.patches.Rectangle'),在 onclick 函数中使用时未被检测到
  • baronclick() 中的一个局部变量。您可以通过在onclick() 开头添加一行来将其更改为全局:global bar
  • 是的,但是 cmp_val 函数中的 bar[i].set_facecolor('') 是 (class 'matplotlib.patches.Rectangle')

标签: python pandas numpy matplotlib


【解决方案1】:

我不确定我是否理解您希望如何标准化您的颜色编码,但我重写了您的代码以使其正常工作。希望您能够根据需要调整代码:

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import pandas as pd
import numpy as np

np.random.seed(12345)

df = pd.DataFrame([np.random.normal(32000, 200000, 3650),
                   np.random.normal(43000, 100000, 3650),
                   np.random.normal(43500, 140000, 3650),
                   np.random.normal(48000, 70000, 3650)],
                  index=[1992, 1993, 1994, 1995])
df = df.T
n = len(df)
std = df.std()
means = df.mean()

ci = (1.96 * std / (n ** 0.5))
cu = list(means + ci)
cl = list(means - ci)
yerror = list(zip(cl, cu))
lab = list(df.columns)
x = np.arange(len(lab))

my_cmap = plt.cm.get_cmap('coolwarm_r')
my_norm = mcolors.Normalize(vmin=-means.max(), vmax=means.max())


def color_bars(val, rectangles, cmap, norm):
    heights = np.array([b.get_height() for b in rectangles])
    diff = heights - val
    colors = cmap(norm(diff))
    for rectangle, color in zip(rectangles, colors):
        rectangle.set_facecolor(color)
    fig.canvas.draw()


fig, ax = plt.subplots()
bars = ax.bar(x, means, width=x[1] - x[0], edgecolor='black', yerr=ci, capsize=20)
hline = ax.axhline(y=0, c='lightslategray', linestyle=':')
ax.set_xticks(x)
ax.set_xticklabels(lab)


def onclick(event):
    if event.inaxes:
        ax.set_title('{:.2f}'.format(event.ydata))
        hline.set_ydata([event.ydata, event.ydata])
        color_bars(event.ydata, bars, cmap=my_cmap, norm=my_norm)
        fig.canvas.draw()


fig.canvas.mpl_connect('button_press_event', onclick)

plt.show()

【讨论】:

  • 感谢您的帮助。我知道我的着色条实现不稳定,但现在开始工作了。这个想法是,如果用户 val 大于条形高度,则绘制蓝色,如果用户 val 小于条形高度,则绘制红色,并且着色应遵循渐变。除了选择配色方案coolwarm而不是colorwarm_r之外,您是正确的
猜你喜欢
  • 2017-09-03
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 2012-02-26
  • 2012-07-30
  • 2017-10-26
  • 1970-01-01
  • 2015-12-19
相关资源
最近更新 更多