如何根据 Slider/Dropdown 的用户输入过滤 CustomJS 脚本中的 ColumnDataSource

问题描述 投票:0回答:1

我想制作一个滑块,让用户根据数据帧中的一列(时间列)过滤绘图。

我尝试了以下方法:

from bokeh.io import output_notebook
from bokeh.plotting import figure, show, save
from bokeh.models import Tabs, TabPanel,Span,TabPanel, Tabs,HoverTool, RangeTool, CustomJS, ColumnDataSource, CheckboxButtonGroup, Slider, Div, RangeSlider, LinearAxis, LabelSet
from bokeh.layouts import column
from bokeh.palettes import Category10, Category20c,Greys256, Turbo256, Viridis256, Inferno256
from bokeh.embed import components
from bokeh.transform import cumsum


sample_data = {'Time': [9, 10, 11, 12, 12, 12, 13, 14, 1, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 14],
 'A': ['eggs',  'eggs',  'eggs',  'eggs',  'eggs',  'eggs',  'banana',  'banana',  'banana',  'banana',  
       'banana',  'milk',  'milk',  'milk',  'milk',  'milk',  'sugar',  'sugar',  'sugar',  'sugar'],
 'X': ['id1',  'id2',  'id3',  'id4',  'id5',  'id6',  'id7',  'id8',  'id9',  'id10',  'id11',  'id12',  'id13',  'id14',  'id15',
  'id16',  'id17',  'id18',  'id19',  'id20'],
 'Y': [26,  21, 49,  28,  22,  31,  33,  45,  42,  27,  11,  12,  42,  43,  36,  43,  30,  41,  16,  21]}

source = ColumnDataSource(sample_data)

TOOLTIPS= [
    ("X","@X"),
    ("Y", "@Y"),
    ("A", "@A"),
    ("Time", "@Time"),
    ]

plot = figure(x_range = source.data['X'], tooltips = TOOLTIPS,sizing_mode = 'stretch_width', tools = ('pan','xpan','ypan','hover','box_zoom','zoom_in','zoom_out','reset'))

plot.circle("X", "Y", source = source,size = 10 )
plot.title.text = 'All Values'

# Set up Slider widget
number_slider = RangeSlider(
    start=min(source.data['Time']),
    end=max(source.data['Time']),
    step = 1,
    value=(min(source.data['Time']),max(source.data['Time'])),
    title="Time Window",
)
  
# Set up CustomJS callback
custom_js = CustomJS(
    args={  # the args parameter is a dictionary of the variables that will be accessible in the JavaScript code
        "plot":plot,  # the first variable will be called "plot" and links to the largest_carriers_plot Python object
        "x": source.data["X"],  # links to list of X in the source ColumnDataSource
        "time": source.data["Time"] #links to list of times in the source
    },
    code="""
    const start = this.value[0] //start time value
    const end = this.value[1] //end time value
        
    // Need code here that filters the data accordingly (selects the rows for which the time 'Time' value >= start and <= end)
    plot.x_range.change.emit()
    """
    )


# Add callback to slider widget
number_slider.js_on_change("value", custom_js)

layout = column([number_slider, plot], sizing_mode="stretch_width")
show(layout)

我希望 JS 脚本选择时间“Time”值 >= start 的行并且 <= end.I'm not well versed with Javascript so I am unsure on how to proceed. Any help is appreciated. Thanks.

javascript python bokeh
1个回答
0
投票

您可以通过相应地更新绘图的

x_range
ColumnDataSource
中的数据来实现此目的。 示例:

// Set up CustomJS callback
custom_js = CustomJS(
    args={  
        "plot": plot,
        "source": source,
        "x_range": plot.x_range,
    },
    code="""
    const start = cb_obj.value[0];
    const end = cb_obj.value[1];

    // Filter data based on time range
    const filtered_data = source.data['Time'].map((time, index) => {
        if (time >= start && time <= end) {
            return index;
        }
        return null;
    }).filter(index => index !== null);

    // Update x_range to match the filtered data
    x_range.factors = source.data['X'].filter((_, index) => filtered_data.includes(index));

    // Trigger plot update
    source.change.emit();
    """
)

// Add callback to slider widget
number_slider.js_on_change("value", custom_js)

© www.soinside.com 2019 - 2024. All rights reserved.