首页 > 解决方案 > 在主轴上的 vbar_stacked 图和次轴上的线图的图中,主要 y_range 不会更新

问题描述

我正在 Bokeh 上同时绘制 vbar_stacked 和线图,主 y 轴上的条形图和辅助轴上的线。该图工作正常,当使用选项按钮更新数据时,数据会相应更改,辅助轴也会发生变化,但主轴保持不变。

######## 1. Importing 
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.palettes import Category20c
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, Select, LinearAxis, Range1d

######## 2. A poor fictional data example
df=pd.DataFrame({'Col1':[45101.023283,41381.466914,7668.987818,
          4682.412413,4677.391936, 4668.987818],
    'Col2':[35101.023283,51381.466914,5668.987818,
          3682.412413,4677.391936, 3668.987818]})

df['Col3']=3*df['Col1']

df['ID_group']='A'
df['ID_group'][3:]='B'

df['ID_sim']=['a','b','c','d','e','f']

df=df.set_index(['ID_group','ID_sim'])

# Defining the col for bar plotting
col_bars=['Col1','Col2']

#Defining the cols for line plotting
col_line='Col3'

######## 3. The excerpt extracted from my original code

### Segmentar o DF para Transformacao em Dados de Torta
df_plot=df.loc['A']

### Convertendo o df_plot em ColumnDataSource
source=ColumnDataSource(df_plot)

### Criacao da Figura para Plot, com coluna_categoria como eixo x
p = figure(x_range=list(df_plot.index))

### ColorMap para Cores da Legenda
cmap=Category20c[20][:len(col_bars)]

### Plot das Colunas
barra = p.vbar_stack(col_bars, x='ID_sim', width=0.9,source=source, 
                 color=cmap, line_color='black', line_width=0.6)

### Impondo o limite minimo do eixo y
p.y_range.start=0

### Impondo o limite máxximo do eixo y
p.y_range.end=max(df_plot[col_bars].sum(axis=1))*1.1  

### Caso coluna_linha nao seja vazio,inserir plot secundario
if list(col_line):
    ### Definir eixo secundario
    p.extra_y_ranges={'y_secundario':Range1d(start=0,
                                                end=float(df_plot[col_line].sum().max())*1.1)}
    ### Adicionar o eixo ao layout
    p.add_layout(LinearAxis(y_range_name='y_secundario'),'right')

    ### Plotar a coluna_linha
    linha = p.line(x='ID_sim',y=col_line,source=source,
               color='firebrick',y_range_name='y_secundario')

    ### Plotando o marcador da linha
    circulo = p.circle(x='ID_sim',y=col_line,source=source,color='firebrick',
                 fill_color='white',size=10,y_range_name='y_secundario')  

### Criacao do Dropbox Menu para Selecao do Conjunto de Analise
select_option = Select(title='ID',
                             options=['A','B'], value='A')


### Criacao de Callback que atualiza o plot conforme selecao do menu select_conjunto         
def update_plot(attr,old,new):
    ### Coleta do valor selecionado no menu select_conjunto
    conjunto = select_option.value

    ### Resegmentar o DF para Transformacao em Dados de Torta
    df_plot=df.loc[conjunto]

    ### Atualizando os dados do plot
    source.data={i:df_plot.reset_index()[i] for i in df_plot.reset_index().columns}

    ### Atualizando o eixo de categorias
    p.x_range.factors=list(df_plot.index)

    ### Atualizando o eixo y principal
    p.y_range.end=max(df_plot[col_bars].sum(axis=1))*1.1

    ### Atualizando eixo y secundário
    p.extra_y_ranges['y_secundario'].end=max(df_plot[col_line])*1.1

select_option.on_change('value',update_plot)

### Criacao do Layout com o Grafico e os Menus    
layout=row(p,select_option,sizing_mode='stretch_width')
curdoc().add_root(layout)


一切正常,除了屏幕中 y_range 的变化......当我打印 p.y_range.end 值时,它应该是......

标签: pythonpython-2.7bokeh

解决方案


因此,我认为与默认 y 范围存在某种奇怪的交互,因为它是一个 auto-ranging DataRange1d。如果你设置一个普通的Range1d

### Impondo o limite minimo do eixo y
#p.y_range.start=0

### Impondo o limite máxximo do eixo y
#p.y_range.end=max(df_plot[col_bars].sum(axis=1))*1.1

# Do this instead of the above two lines
p.y_range = Range1d(start=0, end=max(df_plot[col_bars].sum(axis=1))*1.1)

然后事情对我有用。


推荐阅读