python - 如何在 HoloViews/Bokeh 中的绘图之间创建带有小部件(选择器)和交互性(点击流)的仪表板?
问题描述
我正在尝试创建一个包含两个图(热图和折线图)和一个小部件(选择器)的仪表板:
- 当您从小部件中选择一个选项时,两个图都会更新;
- 当您点击第一个图时,第二个图会根据点击信息更新。
目前我正在尝试在 HoloViews 中进行操作。看起来这应该很容易做到,但我不知何故无法绕开它。
下面的代码显示了它的外观。但是,选择器没有以任何方式连接到仪表板,因为我不知道该怎么做。
import pandas as pd
import numpy as np
import panel as pn
import holoviews as hv
hv.extension('bokeh')
def create_test_df(k_features, n_tickers=5, m_windows=5):
start_date = pd.Timestamp('01-01-2020')
window_len = pd.Timedelta(days=1)
cols = ['window_dt', 'ticker'] + [f'feature_{i}' for i in range(k_features)]
data = {c: [] for c in cols}
for w in range(m_windows):
window_dt = start_date + w*window_len
for t in range(n_tickers):
ticker = f'ticker_{t}'
data['window_dt'].append(window_dt)
data['ticker'].append(ticker)
for f in range(k_features):
data[f'feature_{f}'].append(np.random.rand())
return pd.DataFrame(data)
k_features = 3
features = [f'feature_{i}' for i in range(k_features)]
df = create_test_df(k_features)
selector = pn.widgets.Select(options=features)
heatmap = hv.HeatMap(df[['window_dt', 'ticker', f'{selector.value}']])
posxy = hv.streams.Tap(source=heatmap, x='01-01-2020', y='ticker_4')
def tap_heatmap(x, y):
scalar = np.random.randn()
x = np.linspace(-2*np.pi, 2*np.pi, 100)
data = list(zip(x, np.sin(x*scalar)))
return hv.Curve(data)
pn.Row(heatmap, hv.DynamicMap(tap_heatmap, streams=[posxy]), selector)
解决方案
好的,我终于明白了。结果证明它很简单(正如预期的那样)但不是很直观。基本上,应该使用不同的方法来实现选择器(下拉菜单)。此类示例的工作代码如下:
import pandas as pd
import numpy as np
import panel as pn
import holoviews as hv
hv.extension('bokeh')
def create_test_df(k_features, n_tickers=5, m_windows=5):
start_date = pd.Timestamp('01-01-2020')
window_len = pd.Timedelta(days=1)
cols = ['window_dt', 'ticker'] + [f'feature_{i}' for i in range(k_features)]
data = {c: [] for c in cols}
for w in range(m_windows):
window_dt = start_date + w*window_len
for t in range(n_tickers):
ticker = f'ticker_{t}'
data['window_dt'].append(window_dt)
data['ticker'].append(ticker)
for f in range(k_features):
data[f'feature_{f}'].append(np.random.rand())
return pd.DataFrame(data)
def load_heatmap(feature):
return hv.HeatMap(df[['window_dt', 'ticker', f'{feature}']])
def tap_heatmap(x, y):
scalar = np.random.randn()
x = np.linspace(-2*np.pi, 2*np.pi, 100)
data = list(zip(x, np.sin(x*scalar)))
return hv.Curve(data)
k_features = 3
features = [f'feature_{i}' for i in range(k_features)]
df = create_test_df(k_features)
heatmap_dmap = hv.DynamicMap(load_heatmap, kdims='Feature').redim.values(Feature=features)
posxy = hv.streams.Tap(source=heatmap_dmap, x='01-01-2020', y='ticker_0')
sidegraph_dmap = hv.DynamicMap(tap_heatmap, streams=[posxy])
pn.Row(heatmap_dmap, sidegraph_dmap)
推荐阅读
- testng - Citrus-framework - DataProvider in a separate class
- mysql - mysql works fine after first time
- graphql - GraphQL & Prisma: why does one redefine types in the application schema when they are already part of the Prisma database schema?
- qt - How to connect a signal from my class to a slot in the MainWindow class?
- php - 如何在屏幕上显示我的输入 php?
- android - 如何在rest full api codeigniter中设置会话
- python-3.x - 如何用python制作集群计算机测试代码?(RPI)
- curl - How delete targeting criterion with twurl?
- bash - aws cli s3 sync: how to exclude multiple files
- android - Are there any thread restrictions on performing operations on the Here SDK Map object?