python - Matplotlib 交互式条形图
问题描述
我正在尝试探索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()
解决方案
我不确定我是否理解您希望如何标准化您的颜色编码,但我重写了您的代码以使其正常工作。希望您能够根据需要调整代码:
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()
推荐阅读
- asynchronous - MySQL 和 Redis 的 Tornado 性能问题
- linux - 查明网络应用程序或服务器是否受到威胁
- azure - 获取托管服务主体 ID,无需 AD 访问权限
- javascript - 编写更改编辑器的 vscode 扩展
- random - 如何使用包含同一文件的树枝多次获取随机值
- javascript - 如何正确地将 fn.apply 与 null 一起使用?
- angular - 错误:StaticInjectorError(DynamicTestModule)[CityService -> Http]: No provider for Http
- qt - 如何在 Android 的共享库中启动事件循环?
- javascript - 根据另一个下拉列表的选定值生成下拉选项
- javascript - magnificPopup 不适用于 webpack