Python Bokeh Slider не освежает сюжет - PullRequest
0 голосов
/ 11 февраля 2019

Я создаю график боке с помощью ползунка, чтобы соответствующим образом обновить график.Есть 2 проблемы с размещенным кодом.1. Сюжет не обновляется в соответствии с ползунком.Пожалуйста, помогите в решении этой проблемы.2. График не отображается с curdoc(), когда используется bokeh serve --show fn.ipynb

Я пытаюсь визуализировать этот CSV-файл.

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, как показано ниже, но все равно не повезло.

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

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

@ Джаспер Большое спасибо.Это работает, но не работает с .loc[(['Tamil Nadu']), :].Причина этого заключается в том, чтобы отфильтровать данные, добавив раскрывающийся список с боке или объект переключателя, и обновить график на основе фильтров.Приведенный ниже код работает, только если .loc[(['Tamil Nadu']), :] удален.Есть ли другой способ исправить это, пожалуйста?

def update_plot(attr, old, new):
    yr = slider.value
    new_data = {
        'x'        : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].Area.tolist(),
        'y'        : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].Production.tolist(),
        'state'    : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].index.get_level_values('State_Name').tolist(),
        'district' : crop_dt[crop_dt.index.get_level_values('Crop_Year')==yr].loc[(['Tamil Nadu']), :].index.get_level_values('District_Name').tolist()
    }
    source.data = new_data
0 голосов
/ 13 февраля 2019

Было много проблем при попытке выполнить ваш код, и я изменил некоторые вещи, поэтому не стесняйтесь исправлять меня, если что-то сделал не так.

Ошибка была вызвана созданием ColumnDataSource,Мне пришлось изменить значение уровня на Crop_Year вместо Year.loc 'ABC' также вызвал ошибку, поэтому я тоже ее удалил (и мне пришлось добавить source = ColumnDataSource({, вы, вероятно, забыли скопировать это)

Я также добавил выпадающее меню, чтобы можно было только показывать данныеиз одного района.

Кроме того, я не совсем уверен, возможно ли запустить сервер Bokeh, предоставив файл .ipynb для --serve.Но не надо приставать ко мне, я никогда не пользуюсь ноутбуками.Я проверил это с помощью файла .py.

#!/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)
...