简体   繁体   English

散景 Python:Select 下拉列表正在更新 ColumnDataSource 但不更新图表

[英]Bokeh Python: Select dropdown is updating ColumnDataSource but not updating the graph

I'm new to Bokeh and I'm trying to create an interactive plot of weather data.我是 Bokeh 的新手,我正在尝试创建天气数据的交互式 plot。 There are two Select menus, one for sensor ID (132, 133, ...), and one for variable (Temperature, Dew Point, ...).有两个 Select 菜单,一个用于传感器 ID(132、133,...),另一个用于变量(温度、露点,...)。 When the user changes either value, the graph is supposed to update with the selected data.当用户更改任一值时,图表应该使用所选数据进行更新。

The data I'm using is in a Panda Dataframe, where there is a column 'dt' which contains the one minute interval datetime objects, and the data are in columns that follow the naming convention 'Temp132', 'Temp 133', 'Dew132', 'Dew133', etc. Ideally, the user selected values from the Select menus would be combined to make a string that could be used to extract a data series out of df ('Temp' + '132' would be used to call df['Temp132']).我使用的数据在 Panda Dataframe 中,其中有一列“dt”包含一分钟间隔的日期时间对象,数据位于遵循命名约定“Temp132”、“Temp 133”、“ Dew132'、'Dew133' 等。理想情况下,用户从 Select 菜单中选择的值将组合成一个字符串,该字符串可用于从 df 中提取数据系列('Temp' + '132' 将用于调用 df['Temp132'])。

Using print statements, I can see that when the user changes a value in the Select menu, the ColumnDataSource is getting updated.使用打印语句,我可以看到当用户更改 Select 菜单中的值时,ColumnDataSource 正在更新。 However, it is not updating the graph.但是,它不会更新图表。 I think I'm doing something wrong with the "make_plot" function.我认为我对“make_plot”function 做错了什么。 Also, I am running this using the Bokeh server ( bokeh serve --show bokeh_test.py ).另外,我正在使用 Bokeh 服务器( bokeh serve --show bokeh_test.py )运行它。

Below is an excerpt of my code:以下是我的代码的摘录:

from math import pi
import pandas as pd
from bokeh.io import curdoc
from bokeh.plotting import figure
from bokeh.layouts import row, column
from bokeh.models.widgets import Select
from bokeh.models import DatetimeTickFormatter, ColumnDataSource
import datetime

def get_dataset(src, height, var, dt):
    var_str = var_z[var]['var']
    z_str   = var_z[height]['z']
    df_sub =src[[var_str+z_str]].copy()
    df_sub['dt'] = dt
    df_sub = pd.DataFrame(data=df_sub.values, columns=[var_str+height, 'dt'])
    return ColumnDataSource(data=df_sub)

def make_plot(in_source, y_label_var):
    var = variable_select.value
    z   = height_select.value
    var_str = var_z[var]['var']
    plot = figure(plot_width=800, plot_height=800, title="Data ", x_axis_label = 'Date and Time', y_axis_label = y_label_var)
    plot.line('dt', var_str+z, line_width=2, source=in_source)
    plot.xaxis.formatter=DatetimeTickFormatter( days=["%m/%d/%Y %H:%M"],
        months=["%m/%d/%Y %H:%M"],
        hours=["%m/%d/%Y %H:%M"],
        minutes=["%m/%d/%Y %H:%M"])
    plot.xaxis.major_label_orientation = pi/4

    return plot

def update_plot(attr, old, new):
    var = variable_select.value
    z   = height_select.value
    plot.title.text = var_z[var]['title'] + " " + var_z[z]['title']
    src = get_dataset(df, var_z[z]['z'], var_z[var]['title'], dt)

    print(source.data)
    source.data = src.data
    print(source.data)

#-----------------------------------------------------------------------------

init_height = '132'
init_var    = 'Temperature'

var_z = {'Temperature'        : {'var': 'Temp',         'title': 'Temperature',},
         'Dew Point'          : {'var': 'Dew',          'title': 'Dew Point',},
         'Mean Wind Direction': {'var': 'MeanWindDir',  'title': 'Mean Wind Direction',},
         'Mean Wind Speed'    : {'var': 'MeanWindSpeed','title': 'Mean Wind Speed',},
         'Peak Wind Speed'    : {'var': 'PeakWindSpeed','title': 'Peak Wind Speed',},
         'Peak Wind Direction': {'var': 'PeakWindDir',  'title': 'Peak Wind Direction',},
         'Relative Humidity'  : {'var': 'RH',           'title': 'Relative Humidity',},
         '132' : {'z': '132', 'title': '132',},
         '133' : {'z': '133', 'title': '133',},
         '134' : {'z': '134', 'title': '134',},
         '257' : {'z': '257', 'title': '257',},
         '258' : {'z': '258', 'title': '258',},
         '259' : {'z': '259', 'title': '259',},
         '382' : {'z': '382', 'title': '382',},
         '383' : {'z': '383', 'title': '383',},
         '384' : {'z': '384', 'title': '384',},
         '457' : {'z': '457', 'title': '457',},
         '458' : {'z': '458', 'title': '458',},
         '459' : {'z': '459', 'title': '459',}}

height_select  = Select(value=init_height, title='Height', options = ["132","133","134","257","258","259","382","383","384","457","458","459"])
variable_select= Select(value=init_var, title = 'Variable', options = ["Temperature", "Dew Point", "Mean Wind Direction", "Mean Wind Speed", "Peak Wind Speed", "Peak Wind Direction", "Relative Humidity"] )

df = pd.read_csv('My/File/Path')
dt = df['dt'].to_list()
source = get_dataset(df, init_height, init_var, dt)
plot = make_plot(source, var_z[init_var]['var'])

height_select.on_change('value', update_plot)
variable_select.on_change('value', update_plot)

controls = column(height_select, variable_select)

curdoc().add_root(row(plot,controls))

Thank you for your help!谢谢您的帮助!

You should not assign the .data from one CDS to another CDS.您不应将.data从一个 CDS 分配给另一个 CDS。 In the upcoming Bokeh 2.0 trying to do this will raise an explicit error message.在即将推出的 Bokeh 2.0 中尝试这样做会引发明确的错误消息。 Although it behaves similar to a dict , it is not.尽管它的行为类似于dict ,但事实并非如此。 In order to support all the automatic synchronization between Python and JS the CDS .data is actually a very specialized data structure that has linkages to many other things, and "re-homing" them from one CDS to another is not supported.为了支持 Python 和 JS 之间的所有自动同步,CDS .data实际上是一种非常专业的数据结构,它与许多其他事物有联系,并且不支持将它们从一个 CDS“重新归位”到另一个。 You should only ever assign to .data from a plain python dict您应该只从普通的 python 字典中分配给.data

source.data = { ... } # plain python dict

If you need to adapt a DataFrame there is a .from_df method on CDS that will create the appropriate plain python dict structure you can use to assign from.如果您需要调整 DataFrame 有一个 CDS 上的.from_df方法,它将创建适当的普通 python dict 结构,您可以使用它来分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM