-1

選択したy値(赤い線で表示)が信頼区間内にあるという信頼に基づいて、このグラフの棒を陰影付けしようとしています。以下のクラスの例のrecolorBars()メソッドを参照してください。Matplotlib棒グラフのインタラクティブな再バーバー信頼区間を使用して

私はカラーマップ、Normalize()、およびScalarMappable()を理解していますが、Normalize()に渡す値は各バーの色と陰影を作成するのが難しいです。

最初に生成されたときの私のチャートの外観は次のとおりです。 Interactive Bar Chart Screenshot

上記のチャートを生成するには、chart = interactiveChart()に電話してください。対話性はclickイベントに基づいており、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

を可能な重複:そう、あなたはCMAPと同時にcpickを定義し、それを設定する(-1、1)を使用しなければなりません(http://stackoverflow.com/questions/43133017/how-to-change-colors-automatically-once-a-parameter-is-changed) – ImportanceOfBeingErnest

+0

@ImportanceOfBeingErnest私はそのコードを見て、彼らは似たようなものを実装していたが、別の方法。彼らは色の値を選択するために解決しました。しかし、y値を選択するたびにプロットの各バーを再描画していますが、y値を選択するたびに色を変更したいだけです。 – Adestin

+0

リンクされた質問の解決法では、色のみが変更され、バーはその高さと位置を保持します。私はそこにあなたの例のアプローチの間に全く違いは見ません。このソリューションを使用できると思わない場合は、理由を説明し、実際の問題について具体的に説明する必要があります。 – ImportanceOfBeingErnest

答えて

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

Al [パラメータが変更されると、自動的に色を変更する方法]の

cpick = cm.ScalarMappable(cmap=cmap) 
cpick.set_array(np.linspace(-1, 1)) 

The modifications above got me this result

関連する問題