首页 > 解决方案 > 使用熊猫数据向散景图添加简单的下拉列表

问题描述

我对 Bokeh 很陌生,似乎找不到任何非常好的简单下拉图示例,其中包含来自 pandas 数据框的数据。我正在使用具有 4 个不同键的字典,其中每个键包含一个数据框。

df_vals.keys()
dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])

df_vals['corn'].head()
time    2m_temp_prod    2m_temp_area    total_precip_prod   total_precip_area
0   2020-09-16 00:00:00 299.346777  299.799234  0.000000    0.000000
1   2020-09-16 06:00:00 294.039512  294.443352  0.191070    0.286952
2   2020-09-16 12:00:00 292.959274  293.182931  0.155765    0.216606
3   2020-09-16 18:00:00 301.318046  301.767516  0.421768    0.485691
4   2020-09-17 00:00:00 300.623567  300.979650  0.363572    0.501164

接下来,我可以将此数据添加到源中。

source=ColumnDataSource(data=df_vals['corn'])

从这里绘图很简单。

p1=figure(x_axis_type='datetime')
p1.line(x='time', y='2m_temp_prod',source=source)
show(p1)

这正是我想要的。它绘制了一个以日期时间为 x 轴的线图。但是,现在我想添加一个下拉小部件以在df_vals['corn'](2m_temp_prod 和 total_precip_prod)中的 2 列之间切换。我在下面尝试了这段代码,但它不起作用,我不确定这是否是正确的方法。

def update_plot(attr, old, new):
    if new == 'total_precip_prod': 
        source.data = {
            'x' : df_vals['corn']['time'],
            'y' : df_vals['corn']['total_precip_prod'].cumsum()
        }
select = Select(title="hi", options=['2m_temp_area', 'total_precip_prod'], value='2m_temp_area')
select.on_change('value', update_plot)
 
# Create layout and add to current document
layout = row(select, p1)
curdoc().add_root(layout)

理想情况下,该按钮将有两个选项:temps 和 precip。我该怎么做呢?

标签: pythonpandasbokeh

解决方案


您可以使用 BokehCustomJS 回调根据下拉菜单中的选择来切换绘图的可见性。一个基本示例如下所示:

from bokeh.models import ColumnDataSource, CustomJS, Range1d, Select
from bokeh.plotting import figure, output_notebook, show
from bokeh.layouts import column

import pandas as pd
import numpy as np

# you can also output to an HTML file
output_notebook() 

# toy dataframe with two y columns you can switch between
df = pd.DataFrame(data={
    "x"     : range(0,100),
    "y1"     : np.random.randint(10, 20, 100),
    "y2"     :  np.random.randint(40, 50, 100)
})

# fix the y_range to be the same for two lines
p = figure(y_range=Range1d(0, 60), plot_width=600, plot_height=400)

# shared datasource
source = ColumnDataSource(df)

plot_1 = p.line(x="x", y="y1", color="teal", source=source, line_width=1)
plot_2 = p.line(x="x", y="y2", color="firebrick", source=source, line_width=1)

# initialise the plot with only y1 visible - to match the dropdown default
plot_2.visible = False

# dropdown widget + Javascript code for interactivity
select = Select(title="Plot to show:", value="Line 1", options=["Line 1", "Line 2"])
select.js_on_change("value", CustomJS(args=dict(line_1=plot_1, line_2=plot_2), code="""

line_1.visible = true
line_2.visible = true

if (this.value === "Line 1") {
    line_2.visible = false 
} else {
    line_1.visible = false
}
    
"""))

layout = column(select, p)
show(layout)

在此处输入图像描述


推荐阅读