尝试根据所选y值(由红线表示)位于置信区间内的置信度来遮盖此图表中的条形。请参阅下面的课程示例中的recolorBars()
方法。
虽然我理解了色彩映射,Normalize()
和ScalarMappable()
,但我很难理解要传递给Normalize()的值,以便为每个条形图创建颜色和阴影。
要生成上图所示的图表,请致电chart = interactiveChart()
。交互性基于点击事件,触发setAxHLine()
回调以在选定的Y-val位置设置红色水平条。最终,此方法还将触发recolorBars()
方法。
经测试的代码示例:(请注意,这设置为在Jupyter笔记本中运行。)
%matplotlib notebook
# setup the environment
import pandas as pd
import numpy as np
import statsmodels.stats.api as sms # for confidence intervals
from scipy.stats import sem # another confidence interval shorthand
import matplotlib.cm as cm
import matplotlib.colors as col
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as mpl_il
from matplotlib.widgets import Button, Slider
# from matplotlib.ticker import FormatStrFormatter, ScalarFormatter
class interactiveBarChart:
"""
A base class that can be used for creating clicable charts and solving
the challenges of interpreting plots with confidence intervals.
"""
# basic greys: lighter for regular, darker for emphasis
greys = ['#afafaf','#7b7b7b'] # ticks and boxes, arrows, legend ticks and text
# horizontal bar: nice red
horzo_bar = '#004a80'
# set bar colormap
cmap = cm.get_cmap('RdBu')
# instantiate the class
def __init__(self):
"""
Initialize the data and a new figure.
"""
# seed for data.
np.random.seed(12345)
# get some data to plot
self.df = pd.DataFrame(np.c_[np.random.normal(33500,150000,3650), # np.c_ class to transpose array
np.random.normal(41000,90000,3650),
np.random.normal(41000,120000,3650),
np.random.normal(48000,55000,3650)],
columns=[1992,1993,1994,1995])
# get mean values to plot
self.means = self.df.mean()
# calculate confidence interval high and low
self.c_i = [ sms.DescrStatsW(self.df[i]).tconfint_mean() for i in self.df.columns ]
# calculate the interval whole number
self.intervals = [ invl[-1] - invl[0] for invl in self.c_i ]
# plot the bar chart and make a reference to the rectangles
self.rects = plt.bar(
range(len(self.df.columns)),
self.means,
yerr=self.df.sem().values*1.96,
align='center',
alpha=0.8,
color=self.greys[0],
error_kw=dict(ecolor='gray', lw=2, capsize=7, capthick=2)
)
# set up a starting axhline
self.horzo_slider = plt.axhline(y=40000, xmin=-.1, clip_on=False, zorder=1, color='#e82713')
## TICKS AND TEXT AND SPINES
plt.title('Confidence Interval Interactivity: Click the Chart To Recolor', color=self.greys[1])
plt.xticks(range(len(self.df.columns)), self.df.columns)
# do some formatting
self.formatArtists(plt.gca())
## EVENT HANDLING
# reference the axes and setup pick events
plt.gcf().canvas.mpl_connect('button_press_event', self.setAxHLine)
def formatArtists(self, ax):
"""
Does some recoloring and formatting of the ticks, labels, and spines.
Receives the axes of the current figure.
"""
# recolor the ticks
ax.xaxis.set_tick_params(which='major', colors=self.greys[1])
ax.yaxis.set_tick_params(which='major', colors=self.greys[1])
# recolor the spines
for pos in ['top', 'right', 'bottom', 'left']:
ax.spines[pos].set_edgecolor(self.greys[0])
## EVENT HANDLERS
def setAxHLine(self, event):
"""
Handle the logic for handling bar coloring when the slider
is moved up or down over the confidence intervals.
"""
# remove first axhline
self.horzo_slider.remove()
self.horzo_slider = plt.axhline(y=event.ydata, xmin=-.1, clip_on=False, zorder=1, color='#e82713')
# self.recolorBars(event)
def recolorBars(self, event):
"""
Handles all recoloring of the bars based on the confidence that the selected y-value is within a given interval on the chart.
This function is called on a button press event and receives that data as an argument.
"""
# get the yval
y = event.ydata
# how to determine the shades ?
# abs_diffs = [ abs((mean + conf)-y|) for mean, conf in zip(self.means, self.intervals) ]
# how to pass in the map to get the colors to apply to the bars?
# colors = [ cm.ScalarMappable(norm=col.Normalize(vmin=i[0] , vmax=i[-1]), cmap=self.cmap) for i in self.c_i ]
# apply the colors in a list comprehension
# [ rect.set_color(color) for rect, color in zip(self.rects, colors) ]
def showPlot(self):
"""
Convenience if not using the inline display setup %matplotlib notebook
"""
plt.show()
答案 0 :(得分:1)
这就是我处理这个问题的方法:
def recolorBars(self, event):
y = event.ydata
for i, rect in enumerate(self.rects):
t, p, _ = sms.DescrStatsW(self.df[self.df.columns[i]]).ttest_mean(y)
rect.set_color(self.cpick.to_rgba((1 - p) * t / abs(t)))
在迭代条形图时,首先根据样本均值测试值,然后根据p值设置颜色并测试统计量t:(1 - p)* t
此外,您必须在cmap的同时定义cpick并使用以下方法将其设置为(-1,1)
cpick = cm.ScalarMappable(cmap=cmap)
cpick.set_array(np.linspace(-1, 1))