2015-11-01 9 views
3

我正嘗試使用帶有散景(python)的java腳本回調來在給定選定小部件值時更改堆疊條形圖。我正在使用矩形字形來構建堆疊的條形圖。每個小節都是一個年齡段,我的小工具應該選擇一個年齡段來顯示。我需要做的就是告訴圖表停止渲染其他矩形字形,並將一個年齡段的y值更改爲等於其高度(從而使其成爲一個簡單的條形圖)。散景Python;在ColumnDataSource上使用回調來更改帶有選擇小部件的堆疊條形圖

我有我所有的數據在數組中,但然後我把它變成列表爲了傳遞給回調。我的Java腳本警告告訴我,我的for語句工作,它正在讀取y值罰款。我的回調邏輯可能很時髦/不正確,但我更擔心字形根本不會響應回調而改變。也許這是我在回調中推送數據的方式?謝謝!!

from bokeh.models import Callback, ColumnDataSource, Rect, Select 
from bokeh.plotting import figure, output_file, show, VBox, gridplot, HBox 
import pandas as pd 


#Color Dictionary 
redcolor5 = {u'All ages': "#720017", u'70+ years': "#bd0026", u'50-69 years': "#f03b20", u'15-49 years': "#fd8d3c", u'Under 5 years': "#f4cc63", u'gridline': '#b2ada6', u'background': '#e3e0db', u'axis' : '#aba9a7'} 

#Just a sample of my data 
country_both = ['China', 'India', 'United States', 'Russia', 'Japan', 'Indonesia', 'Germany', 'United Kingdom', 'Italy', 'Brazil'] 
ages_gen = ['Under 5 years', '15-49 years', '50-69 years', '70+ years', 'All ages', 'Age-standardized'] 

height70yr = [919470, 421922, 321125, 193960, 148946, 107822, 97529, 90198, 81107, 76782] 
height50to69 = [640496, 626995, 182338, 195472, 40422, 109242, 44161, 33333, 24964, 64429] 
height15to49 = [126094, 139420, 26159, 43239, 5480, 39040, 6829, 4163, 3571, 16152] 
heightUnder5 = [10210, 43338, 82, 714, 41, 5255, 0, 26, 0, 1201] 

frame = pd.DataFrame({"arBoth_70yr_Cnty": height70yr, "arBoth_5069yr_Cnty": height50to69, "arBoth_1549yr_Cnty": height15to49, "arBoth_5yr_Cnty": heightUnder5}) 
arBoth_70yr_Cnty = frame['arBoth_70yr_Cnty'] 
arBoth_5069yr_Cnty = frame['arBoth_5069yr_Cnty'] 
arBoth_1549yr_Cnty = frame['arBoth_1549yr_Cnty'] 
arBoth_5yr_Cnty = frame['arBoth_5yr_Cnty'] 

#Y Values for Stacked bar chart 
yUnder5 = (arBoth_5yr_Cnty/2).tolist() 
y15to49 = (arBoth_5yr_Cnty+arBoth_1549yr_Cnty/2).tolist() 
y50to69 = (arBoth_5yr_Cnty+arBoth_1549yr_Cnty+arBoth_5069yr_Cnty/2).tolist() 
y70yr = (arBoth_5yr_Cnty+arBoth_1549yr_Cnty+arBoth_5069yr_Cnty+arBoth_70yr_Cnty/2).tolist() 


output_file('UW_TobaccoDeath.html') 

#Figure for Stacked bar chart 
p1 = figure(title="Top Countries with Death Due to Tobacco by Age", 
      x_range=country_both, y_range=[0, max(arBoth_5yr_Cnty+arBoth_1549yr_Cnty+arBoth_5069yr_Cnty+arBoth_70yr_Cnty)], 
      background_fill=redcolor5['background'], 
      plot_width=700, plot_height = 400, 
      outline_line_color= None) 


#source for callback 
source1 = ColumnDataSource(data=dict(x=country_both, yUnder5 = yUnder5, heightUnder5 = heightUnder5, y15to49 = y15to49, height15to49 = height15to49, y50to69 = y50to69, height50to69 = height50to69, y70yr=y70yr, height70yr = height70yr)) 

#Use rect glyphs for stached bars 
p1.rect(x ='x', y ='yUnder5', width =.8, height = 'heightUnder5', source = source1, color=redcolor5['Under 5 years'], alpha=0.8, name = "Under 5") 
p1.rect(x = 'x', y ='y15to49', width = .8, height ='height15to49', source = source1, color=redcolor5['15-49 years'], alpha=0.8, name = "15 to 49") 
p1.rect(x = 'x', y ='y50to69', width = .8, height ='height50to69', source = source1, color=redcolor5['50-69 years'], alpha = .8, name = "50 to 69") 
p1.rect(x = 'x', y ='y70yr', width = .8, height ='height70yr', source = source1, color=redcolor5['70+ years'], alpha = .8, name = "70+ yrs") 


#Java script Callbacks for age 
#I want this to recognize the 70+ year old drop down selection 
#and change the plot so that the height of the glyph is the same as the y value and the 70 year old glyph is the only one that displays 
Callback_Age = Callback(args=dict(source1 = source1), code=""" 
     var f = cb_obj.get('value'); 
     var data = source1.get('data'); 
     var x = data['x']; 

     if (f == '70+ years') { 
      var y = 0; 
      var height = data['height70yr']; 
      alert(height); 
      } 

     data['x'].push(x); 
     data['y'].push(y); 
     data['height'].push(height); 
     source1.trigger('change'); 

    """) 

#Use the Select widget 
dropdown_age = Select(title="Ages:", value=ages_gen[4], options= ages_gen, callback = Callback_Age) 

#Display data 
filters = VBox(dropdown_age) 
tot = HBox(filters, gridplot([[p1]])) 
show(tot) 

回答

3

感謝您研究與菸草有關的傷亡事件!

我的做法是使用4個來源(每個年齡組1個),然後根據所選年齡組手動更改它們。如果選擇15-49歲的年齡組,則關聯的來源y居中(高度爲0),所有其他人的身高設置爲0.我已經完成了「所有年齡」組,但沒有「年齡標準化」。而且我還沒有嘗試調整數字,以更好地看到5歲以下的小組。 哦,我也換成了numpy數組。這只是一個方便的事情,如果您願意,您可以繼續使用Python列表和熊貓幀。

問我,如果您有任何進一步的問題, 蒂埃裏

from bokeh.models import Callback, ColumnDataSource, Rect, Select,CustomJS 
from bokeh.plotting import figure, output_file, show, gridplot 
from bokeh.models.widgets.layouts import VBox,HBox 
import numpy as np 


#Color Dictionary 
redcolor5 = {u'All ages': "#720017", u'70+ years': "#bd0026", u'50-69 years': "#f03b20", u'15-49 years': "#fd8d3c", u'Under 5 years': "#f4cc63", u'gridline': '#b2ada6', u'background': '#e3e0db', u'axis' : '#aba9a7'} 

#Just a sample of my data 
country_both = ['China', 'India', 'United States', 'Russia', 'Japan', 'Indonesia', 'Germany', 'United Kingdom', 'Italy', 'Brazil'] 
ages_gen = ['Under 5 years', '15-49 years', '50-69 years', '70+ years', 'All ages', 'Age-standardized'] 

height70yr = np.array([919470, 421922, 321125, 193960, 148946, 107822, 97529, 90198, 81107, 76782]) 
height50to69 = np.array([640496, 626995, 182338, 195472, 40422, 109242, 44161, 33333, 24964, 64429]) 
height15to49 = np.array([126094, 139420, 26159, 43239, 5480, 39040, 6829, 4163, 3571, 16152]) 
heightUnder5 = np.array([10210, 43338, 82, 714, 41, 5255, 0, 26, 0, 1201]) 
zeros = np.zeros(len(country_both)) 


#Y Values for Stacked bar chart 
yUnder5 = heightUnder5/2.0 
y15to49 = yUnder5 + height15to49/2.0 
y50to69 = y15to49 + height50to69/2.0 
y70yr = y50to69 + height70yr/2.0 


output_file('UW_TobaccoDeath.html') 

#Figure for Stacked bar chart 
p1 = figure(title="Top Countries with Death Due to Tobacco by Age", 
      x_range=country_both, y_range=[0, np.amax([y70yr+height70yr])], 
      background_fill=redcolor5['background'], 
      plot_width=700, plot_height = 600, 
      outline_line_color= None) 


#source for callback 
source1 = ColumnDataSource(data=dict(x=country_both, y = yUnder5, y_full = yUnder5, height = heightUnder5, height_full = heightUnder5 ,height_zeros = zeros, y_zeros = heightUnder5/2.0)) 
source2 = ColumnDataSource(data=dict(x=country_both, y = y15to49, y_full = y15to49, height = height15to49, height_full = height15to49,height_zeros = zeros, y_zeros = height15to49/2.0)) 
source3 = ColumnDataSource(data=dict(x=country_both, y = y50to69, y_full = y50to69, height = height50to69, height_full = height50to69,height_zeros = zeros , y_zeros = height50to69/2.0)) 
source4 = ColumnDataSource(data=dict(x=country_both, y = y70yr, y_full = y70yr, height = height70yr, height_full = height70yr,height_zeros = zeros, y_zeros = height70yr/2.0)) 

#Use rect glyphs for stached bars 
p1.rect(x ='x', y ='y', width =.8, height = 'height', source = source1, color=redcolor5['Under 5 years'], alpha=0.8, name = "Under 5") 
p1.rect(x = 'x', y ='y', width = .8, height ='height', source = source2, color=redcolor5['15-49 years'], alpha=0.8, name = "15 to 49") 
p1.rect(x = 'x', y ='y', width = .8, height ='height', source = source3, color=redcolor5['50-69 years'], alpha = .8, name = "50 to 69") 
p1.rect(x = 'x', y ='y', width = .8, height ='height', source = source4, color=redcolor5['70+ years'], alpha = .8, name = "70+ yrs") 

#Java script Callbacks for age 
#I want this to recognize the 70+ year old drop down selection 
#and change the plot so that the height of the glyph is the same as the y value and the 70 year old glyph is the only one that displays 
Callback_Age = CustomJS(args={'source1': source1,'source2': source2,'source3': source3,'source4': source4}, code=""" 
     var f = cb_obj.get('value'); 
     var data1 = source1.get('data'); 
     var data2 = source2.get('data'); 
     var data3 = source3.get('data'); 
     var data4 = source4.get('data'); 
     if (f == 'Under 5 years') { 
      data3['height'] = data3['height_zeros']; 
      data2['height'] = data2['height_zeros']; 
      data4['height'] = data4['height_zeros']; 
      data1['y'] = data1['y_zeros']; 
      data1['height'] = data1['height_full']; 
      source1.trigger('change'); 
      source2.trigger('change'); 
      source3.trigger('change'); 
      source4.trigger('change'); 
      } 
     if (f == '15-49 years') { 
      data1['height'] = data1['height_zeros']; 
      data3['height'] = data3['height_zeros']; 
      data4['height'] = data4['height_zeros']; 
      data2['y'] = data2['y_zeros']; 
      data2['height'] = data2['height_full']; 
      source1.trigger('change'); 
      source2.trigger('change'); 
      source3.trigger('change'); 
      source4.trigger('change'); 
      } 

     if (f == '50-69 years') { 
      data1['height'] = data1['height_zeros']; 
      data2['height'] = data2['height_zeros']; 
      data4['height'] = data4['height_zeros']; 
      data3['y'] = data3['y_zeros']; 
      data3['height'] = data3['height_full']; 
      console.log('data3',data3) 
      source1.trigger('change'); 
      source2.trigger('change'); 
      source3.trigger('change'); 
      source4.trigger('change'); 
      } 
     if (f == '70+ years') { 
      data1['height'] = data1['height_zeros']; 
      data2['height'] = data2['height_zeros']; 
      data3['height'] = data3['height_zeros']; 
      data4['y'] = data4['y_zeros']; 
      data4['height'] = data4['height_full']; 
      source1.trigger('change'); 
      source2.trigger('change'); 
      source3.trigger('change'); 
      source4.trigger('change'); 
      } 
     if (f == 'All ages') { 
      data1['height'] = data1['height_full']; 
      data1['y'] = data1['y_full']; 
      data2['height'] = data2['height_full']; 
      data2['y'] = data2['y_full']; 
      data3['height'] = data3['height_full']; 
      data3['y'] = data3['y_full']; 
      data4['height'] = data4['height_full']; 
      data4['y'] = data4['y_full']; 
      source1.trigger('change'); 
      source2.trigger('change'); 
      source3.trigger('change'); 
      source4.trigger('change'); 
      } 



    """) 
#Use the Select widget 
dropdown_age = Select(title="Ages:", value=ages_gen[4], options= ages_gen, callback = Callback_Age) 

#Display data 
filters = VBox(dropdown_age) 
tot = HBox(filters, gridplot([[p1]])) 
show(tot) 
+0

wowza!非常感謝!! –

+0

創建CustomJS的使用。一個問題。你能爲顏色(年齡段)添加一個圖例嗎? – PR102012