亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Bokeh自定義JS回調日期范圍滑塊

Bokeh自定義JS回調日期范圍滑塊

翻過高山走不出你 2024-01-27 15:25:58
我嘗試創建一個交互式圖表,繪制值 Y 與日期 X 的關系。到目前為止一切順利?,F在我想通過 DateRangeSlider 調整 x 軸的限制 xmin 和 xmax 但我不理解 js 回調函數(我想在最后有一個獨立的 html 文件),因為我什至不知道如何從函數內部打印值并且不產生任何錯誤,我不知道現在該怎么辦。這是代碼的運行示例:import numpy as npimport pandas as pdfrom datetime import datetimefrom bokeh.models import ColumnDataSource, DatetimeTickFormatter, HoverToolfrom bokeh.models.widgets import DateRangeSliderfrom bokeh.layouts import layout, columnfrom bokeh.models.callbacks import CustomJSfrom bokeh.plotting import figure, output_file, show, savedatesX = pd.date_range(start='1/1/2018', periods=100)valuesY = pd.DataFrame(np.random.randint(0,25,size=(100, 1)), columns=list('A'))source = ColumnDataSource(data={'x': datesX, 'y': valuesY['A']})?# output to static HTML fileoutput_file('file.html')hover = HoverTool(tooltips=[('Timestamp', '@x{%Y-%m-%d %H:%M:%S}'), ('Value', '@y')],? ? ? ? ? ? ? ? ? ? ? ? ? ?formatters={'x': 'datetime'},)? ??date_range_slider = DateRangeSlider(title="Zeitrahmen", start=datesX[0], end=datesX[99], \? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? value=(datesX[0], datesX[99]), step=1, width=300)# create a new plot with a title and axis labelsp = figure(title='file1', x_axis_label='Date', y_axis_label='yValue',? x_axis_type='datetime',?? ? ? ? ? ? ? ?tools="pan, wheel_zoom, box_zoom, reset", plot_width=300, plot_height=200)# add a line renderer with legend and line thickness? ??p.line(x='x', y='y', source=source, line_width=2)p.add_tools(hover)? ? ? ?callback = CustomJS(args=dict(source=source), code="""? ? ##### what to do???? ? source.change.emit();? ? """)? ??date_range_slider.js_on_change('value', callback)layout = column(p, date_range_slider)# show the resultsshow(layout)
查看完整描述

4 回答

?
慕沐林林

TA貢獻2016條經驗 獲得超9個贊

source.data更改滑塊時需要創建一個新的。為此,您還需要一個不可source更改的“備份” ,并作為要包含哪些數據的參考。將兩者作為參數傳遞給回調函數使它們可用于 Javascript 代碼。


datesX = pd.date_range(start='1/1/2018', periods=100)

valuesY = pd.DataFrame(np.random.randint(0,25,size=(100, 1)), columns=list('A'))


# keep track of the unchanged, y-axis values

source = ColumnDataSource(data={'x': datesX, 'y': valuesY['A']})?

source2 = ColumnDataSource(data={'x': datesX, 'y': valuesY['A']})


# output to static HTML file

output_file('file.html')


hover = HoverTool(

? ? tooltips=[('Timestamp', '@x{%Y-%m-%d %H:%M:%S}'), ('Value', '@y')],

? ? formatters={'x': 'datetime'},)

? ??

date_range_slider = DateRangeSlider(

? ? title="Zeitrahmen", start=datesX[0], end=datesX[99],

? ? value=(datesX[0], datesX[99]), step=1, width=300)


# create a new plot with a title and axis labels

p = figure(

? ? title='file1', x_axis_label='Date', y_axis_label='yValue',

? ? y_range=(0, 30), x_axis_type='datetime',

? ? tools="pan, wheel_zoom, box_zoom, reset",

? ? plot_width=600, plot_height=200)


# add a line renderer with legend and line thickness

? ??

p.line(x='x', y='y', source=source, line_width=2)

p.add_tools(hover)


callback = CustomJS(args=dict(source=source, ref_source=source2), code="""

? ??

? ? // print out array of date from, date to

? ? console.log(cb_obj.value);?

? ??

? ? // dates returned from slider are not at round intervals and include time;

? ? const date_from = Date.parse(new Date(cb_obj.value[0]).toDateString());

? ? const date_to = Date.parse(new Date(cb_obj.value[1]).toDateString());

? ??

? ? const data = source.data;

? ? const ref = ref_source.data;

? ??

? ? const from_pos = ref["x"].indexOf(date_from);

? ? // add + 1 if you want inclusive end date

? ? const to_pos = ref["x"].indexOf(date_to);

? ? ? ??

? ? // re-create the source data from "reference"

? ? data["y"] = ref["y"].slice(from_pos, to_pos);

? ? data["x"] = ref["x"].slice(from_pos, to_pos);

? ??

? ? source.change.emit();

? ? """)

? ??

date_range_slider.js_on_change('value', callback)

layout = column(p, date_range_slider)


# show the results

show(layout)


查看完整回答
反對 回復 2024-01-27
?
富國滬深

TA貢獻1790條經驗 獲得超9個贊

我發現上面的答案不起作用,因為數據的時間戳ref_source與來自散景滑塊對象(cb_obj)的解析時間戳不同。


例如,ref_source數據中的時間戳在使用 進行解析時會創建以下輸出new Date(source.data.["x"]);:


01/01/2020 02:00:00


來自散景滑塊對象的時間戳cb_obj始終為00:00:00。因此使用時無法找到時間戳const from_pos = ref["date"].indexOf(date_from);。


為了正確解析日期,ref_source我創建了一個新數組new_ref并將正確解析的日期添加到該數組中。不過,我必須在這里強調,我不是 JavaScript 專家,我很確定在這里可以更有效地編寫代碼。


這是我的工作示例:


// print out array of date from, date to

console.log(cb_obj.value); 


// dates returned from slider are not at round intervals and include time;

const date_from = Date.parse(new Date(cb_obj.value[0]).toDateString());

const date_to = Date.parse(new Date(cb_obj.value[1]).toDateString());

console.log(date_from, date_to)


// Creating the Data Sources

const data = source.data;

const ref = ref_source.data;


// Creating new Array and appending correctly parsed dates

let new_ref = []

ref["x"].forEach(elem => {

    elem = Date.parse(new Date(elem).toDateString());

    new_ref.push(elem);

    console.log(elem);

})


// Creating Indices with new Array

const from_pos = new_ref.indexOf(date_from);

const to_pos = new_ref.indexOf(date_to) + 1;



// re-create the source data from "reference"

data["y"] = ref["y"].slice(from_pos, to_pos);

data["x"] = ref["x"].slice(from_pos, to_pos);


source.change.emit();

我希望它對你有一點幫助:)


查看完整回答
反對 回復 2024-01-27
?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

有趣的問題和討論。添加以下兩行(其中一行直接從文檔中提?。┰试S滑塊在不使用 CustomJS 和 js_on_change 函數的情況下工作 - 使用 js_link 函數代替:

date_range_slider.js_link('value', p.x_range, 'start', attr_selector=0)
date_range_slider.js_link('value', p.x_range, 'end', attr_selector=1)


查看完整回答
反對 回復 2024-01-27
?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

使用 CustonJS 直接更改繪圖 x_range 而不是過濾數據源。


callback = CustomJS(args=dict(p=p), code="""

    p.x_range.start = cb_obj.value[0]

    p.x_range.end = cb_obj.value[1]

    p.x_range.change.emit()

    """)


date_range_slider.js_on_change('value_throttled', callback)


查看完整回答
反對 回復 2024-01-27
  • 4 回答
  • 0 關注
  • 204 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號