Python bokeh滑块不刷新情节 [英] Python bokeh slider not refreshing plot

查看:58
本文介绍了Python bokeh滑块不刷新情节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用滑块创建一个散景图,以相应地刷新图.发布的代码有2个问题. 1.不会按照滑块刷新图.请帮助提供解决此问题的方法. 2.使用bokeh serve --show fn.ipynb时,图不显示curdoc()

I am creating a bokeh plot with a slider to refresh plot accordingly. There are 2 issues with the code posted. 1. The plot is not refreshed as per the slider. Please help in providing a fix for this issue. 2. Plot is not displayed with curdoc() when bokeh serve --show fn.ipynb is used

我正在尝试可视化 CSV文件.

I'm trying to visualise this CSV file.

import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource, CategoricalColorMapper, HoverTool, Slider
from bokeh.plotting import figure, curdoc
from bokeh.palettes import viridis
from bokeh.layouts import row, widgetbox

#Importing and processing data file 
crop = pd.read_csv('crop_production.csv') 

#Cleaning Data 
crop.fillna(np.NaN) 
crop['Season'] = crop.Season.str.strip() 

#Removing Whitespace #Filtering the dataset by Season 
crop_season = crop[crop.Season == 'Whole Year'] 
crop_dt = crop_season.groupby(['State_Name', 'District_Name', 'Crop_Year']).mean().round(1)

#Creating Column Data Source
source = ColumnDataSource({
        'x'        : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].Area,
        'y'        : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].Production,
        'state'    : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].index.get_level_values('State_Name'),
        'district' : crop_dt[crop_dt.index.get_level_values('Year')==2001].loc[(['ABC']), :].index.get_level_values('District_Name')
})


#Creating color palette for plot
district_list = crop_dt.loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').unique().tolist()
call_colors = viridis(len(district_list))
color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)


# Creating the figure
#xmin, xmax = min(data.Crop_Year), max(data.Crop_Year)
#ymin, ymax = min(data.Production), max(data.Production)
p = figure(
    title = 'Crop Area vs Production',
    x_axis_label = 'Area',
    y_axis_label = 'Production',
    plot_height=900, 
    plot_width=1200,
    tools = [HoverTool(tooltips='@district')]
          )
p.circle(x='x', y='y', source=source, size=12, alpha=0.7, 
         color=dict(field='district', transform=color_mapper),
         legend='district')
p.legend.location = 'top_right'


def update_plot(attr, old, new):
    yr = slider.value
    new_data = {
        'x'        : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].Area,
        'y'        : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].Production,
        'state'    : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].index.get_level_values('State_Name'),
        'district' : crop_dt[crop_dt.index.get_level_values('Year')==yr].loc[(['ABC']), :].index.get_level_values('District_Name')
    }
    source.data = new_data

#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year')
slider.on_change('value',update_plot)

layout = row(widgetbox(slider), p)
curdoc().add_root(layout)
show(layout)

还使用如下所示的CustomJS尝试了其他选项,但还是没有运气.

Also tried a different option using CustomJS as below, but still no luck.

callback = CustomJS(args=dict(source=source), code="""
    var data = source.data;
    var yr = slider.value;
    var x = data['x']
    var y = data['y']
    'x'        = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['ABC']), :].Area;
    'y'        = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['ABC']), :].Production;
    p.circle(x='x', y='y', source=source, size=12, alpha=0.7, 
         color=dict(field='district', transform=color_mapper),
         legend='district');
    }
    source.change.emit();
""")



#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
yr_slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year', callback=callback)
callback.args["slider"] = yr_slider

推荐答案

尝试执行您的代码时遇到很多问题,并且我更改了一些内容,因此,如果做错了什么,请随时纠正我.

Had a lot of issues trying to execute your code and I have changed some things, so feel free to correct me if did something wrong.

该错误是由ColumnDataSource的创建引起的,我必须将级别值更改为Crop_Year而不是Year. loc 'ABC'也会导致错误,因此我也删除了该错误(而且我不得不添加source = ColumnDataSource({,您可能忘了复制它)

The error was caused by the creation of the ColumnDataSource, I had to change the level value to Crop_Year instead of Year. The loc 'ABC' also caused an error so I removed that too (And I had to add source = ColumnDataSource({, you probably forgot to copy that)

我还添加了一个下拉菜单,因此可以只显示一个地区的数据.

I also added a dropdown menu so it's possible to only show the data from one district.

此外,我不太确定是否可以通过向--serve提供.ipynb文件来启动bokeh服务器.但是请不要把我固定在上面,我从不使用笔记本电脑.我已经用.py文件对此进行了测试.

Also, I'm not quite sure if it's possible to start a bokeh server by supplying a .ipynb file to --serve. But don't pin me down on that, I never use notebooks. I've tested this with a .py file.

#!/usr/bin/python3
import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource, CategoricalColorMapper, HoverTool
from bokeh.plotting import figure, curdoc
from bokeh.palettes import viridis
from bokeh.layouts import row, widgetbox
from bokeh.models.widgets import Select, Slider

#Importing and processing data file 
crop = pd.read_csv('crop_production.csv') 

#Cleaning Data 
crop.fillna(np.NaN) 
crop['Season'] = crop.Season.str.strip() 

#Removing Whitespace #Filtering the dataset by Season 
crop_season = crop[crop.Season == 'Whole Year'] 
crop_dt = crop_season.groupby(['State_Name', 'District_Name', 'Crop_Year']).mean().round(1)

crop_dt_year = crop_dt[crop_dt.index.get_level_values('Crop_Year')==2001]
crop_dt_year_state = crop_dt_year[crop_dt_year.index.get_level_values('State_Name')=='Tamil Nadu']

#Creating Column Data Source
source = ColumnDataSource({
    'x': crop_dt_year_state.Area.tolist(), 
    'y': crop_dt_year_state.Production.tolist(), 
    'state': crop_dt_year_state.index.get_level_values('State_Name').tolist(), 
    'district': crop_dt_year_state.index.get_level_values('District_Name').tolist()
})

#Creating color palette for plot
district_list = crop_dt.loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').unique().tolist()
call_colors = viridis(len(district_list))
color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)

# Creating the figure
p = figure(
    title = 'Crop Area vs Production',
    x_axis_label = 'Area',
    y_axis_label = 'Production',
    plot_height=900, 
    plot_width=1200,
    tools = [HoverTool(tooltips='@district')]
          )
glyphs = p.circle(x='x', y='y', source=source, size=12, alpha=0.7, 
         color=dict(field='district', transform=color_mapper),
         legend='district')
p.legend.location = 'top_right'

def update_plot(attr, old, new):
    #Update glyph locations
    yr = slider.value
    state  = select.value
    crop_dt_year = crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr]
    crop_dt_year_state = crop_dt_year[crop_dt_year.index.get_level_values('State_Name')==state]
    new_data = {
        'x': crop_dt_year_state.Area.tolist(), 
        'y': crop_dt_year_state.Production.tolist(), 
        'state': crop_dt_year_state.index.get_level_values('State_Name').tolist(), 
        'district': crop_dt_year_state.index.get_level_values('District_Name').tolist()
    }
    source.data = new_data
    #Update colors
    district_list = crop_dt.loc[([state]), :].index.get_level_values('District_Name').unique().tolist()
    call_colors = viridis(len(district_list))
    color_mapper = CategoricalColorMapper(factors=district_list, palette=call_colors)
    glyphs.glyph.fill_color = dict(field='district', transform=color_mapper)
    glyphs.glyph.line_color = dict(field='district', transform=color_mapper)

#Creating Slider for Year
start_yr = min(crop_dt.index.get_level_values('Crop_Year'))
end_yr = max(crop_dt.index.get_level_values('Crop_Year'))
slider = Slider(start=start_yr, end=end_yr, step=1, value=start_yr, title='Year')
slider.on_change('value',update_plot)

#Creating drop down for state
options = list(set(crop_dt.index.get_level_values('State_Name').tolist()))
options.sort()
select = Select(title="State:", value="Tamil Nadu", options=options)
select.on_change('value', update_plot)

layout = row(widgetbox(slider, select), p)
curdoc().add_root(layout)

这篇关于Python bokeh滑块不刷新情节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆