0

I'm trying to create a dashboard that consists of two plots (heatmap and line graph) and one widget (selector):

  • When you select an option from widget both plots get updated;
  • When you tap on the first plot the second plot is updated based on tap info.

enter image description here

Currently I'm trying to do it in HoloViews. It seems that this should be very easy to do but I somehow can't wrap my head around it.

The code below shows how it should look like. However, the selector is not connected in any way to the dashboard since I don't know how to do it.

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)
yol
  • 19
  • 6
  • I'm no expert with HollowViews/Bokeh, but I will say that [Plotly](https://plotly.com/python/) is a great easy-to-use library with lots of customization options. Here are links for documentation on how to create [line plots](https://plotly.com/python/line-charts/), [heatmaps](https://plotly.com/python/heatmaps/), and [drop-down options](https://stackoverflow.com/questions/64893793/add-index-as-dropdown-menu-in-plotly/64898132#64898132). Also all of these graphs support interactive features like hovering and zooming. – Jacob K Dec 19 '20 at 22:55
  • Thanks for pointing it out. However, it doesn't seem easier to me since I'm quite a beginner myself. Could you provide some more details as to how to implement the task I described, please? – yol Dec 19 '20 at 23:28

1 Answers1

1

Ok I finally got it. It turned out to be simple (just as expected) but not quite intuitive. Basically, different approach for implementing selector (dropdown menu) should be used. Working code for such example is below:

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)
yol
  • 19
  • 6