如何双向关联HoloViews(hvplot)图表X轴与Panel日期时间选择器
问题描述
我已经折腾一周多了,想实现两个功能:
- 制作时间序列图表,可通过日期时间选择器控制X轴范围/缩放。
- 当用图表缩放控件更改X范围时,日期时间选择器同步更新。
目前仅能实现单向关联,但IntSlider等其他控件可正常双向关联。
需求说明:
- 可用单个DatetimeRangePicker或两个DatetimePicker(起始/结束)定义X范围。
- 数据集庞大,需支持datashader渲染。

感谢您的帮助 :)
已尝试方案
最小可复现示例(MRE)及代码如下
- 创建DatetimeRangePicker,用hvplot绘图并设置
xlim=datatimerangepicker。
结果:图表随控件变化,但缩放/平移图表时控件值不更新。 - 用
hv.streams.RangeX捕获X范围变化,通过pn.depends函数生成图表。
结果:缩放/平移可更新控件(速度极慢),更改控件触发AttributeError: 'NoneType' object has no attribute 'id'错误。 - 创建两个DatetimePicker,通过
widget.jslink()与图表x_range双向关联。
结果:图表可加载,但控件和图表操作均无反应。
最小可复现示例(MRE)及失败尝试
创建数据集
import pandas as pd import numpy as np import panel as pn import holoviews as hv import hvplot.pandas hv.extension('bokeh') df = pd.DataFrame({'data': np.random.randint(0, 100, 100)}, index=pd.date_range(start="2022", freq='D', periods=100))
失败方案1:
图表随控件变化,但控件不随图表变化
range_select = pn.widgets.DatetimeRangePicker(value=(df.index[0], df.index[-1])) pn.Column(df.data.hvplot.line(datashade=True, xlim=range_select), range_select)
失败方案2:
速度慢,更改控件触发AttributeError: 'NoneType' object has no attribute 'id'错误
range_select = pn.widgets.DatetimeRangePicker(value=(df.index[0], df.index[-1])) @pn.depends(range_x=range_select.param.value) def make_fig(range_x): fig = df.data.hvplot.line(datashade=True, xlim=range_x) pointer = hv.streams.RangeX(source=fig) tabl = hv.DynamicMap(show_x, streams=[pointer]) # 绘制无用表格以触发功能 return fig + tabl def show_x(x_range): if x_range is not None: range_select.value = tuple([pd.Timestamp(i).to_pydatetime() for i in x_range]) return hv.Table({"start": [x_range[0]], "stop": [x_range[1]]}, ["start", "stop"]) if x_range else hv.Table({}) pn.Column(range_select, make_fig)
失败方案3:
对DatetimePicker无效,但对IntSlider等控件有效
pn.widgets.DatetimePicker._source_transforms = ({}) # 参考相关讨论 # 日期时间范围控件 range_strt = pn.widgets.DatetimePicker() range_end = pn.widgets.DatetimePicker() # 作为对比的整数滑块(此类控件可正常工作) int_start_widget = pn.widgets.IntSlider(start=0, step=int(1e6), end=int(1.7e12)) int_end_widget = pn.widgets.IntSlider(start=0, step=int(1e6), end=int(1.7e12)) points = df.data.hvplot.line(datashade=True) # 生成图表 # 将控件与图表关联: int_start_widget.jslink(points, value="x_range.start", bidirectional=True) int_end_widget.jslink(points, value="x_range.end", bidirectional=True) range_strt.jslink(points, value="x_range.start", bidirectional=True) range_end.jslink(points, value="x_range.end", bidirectional=True) pn.Row(points,pn.Column( range_strt, range_end, int_start_widget, int_end_widget,))
内容的提问来源于stack exchange,提问作者n4321d
相关产品推荐
相关产品推荐

