2

I was able to create two linked plots using holoviews + bokeh backend, basically following this code example.

Here's an example of code from the reference:

import pandas as pd
import numpy as np
import holoviews as hv
import seaborn as sns
from holoviews import opts
hv.extension('bokeh', width=90)

# Declare dataset
df = sns.load_dataset('tips')
df = df[['total_bill', 'tip', 'size']]

# Declare HeatMap
corr = df.corr()
heatmap = hv.HeatMap((corr.columns, corr.index, corr))

# Declare Tap stream with heatmap as source and initial values
posxy = hv.streams.Tap(source=heatmap, x='total_bill', y='tip')

# Define function to compute histogram based on tap location
def tap_histogram(x, y):
    m, b = np.polyfit(df[x], df[y], deg=1)
    x_data = np.linspace(df.tip.min(), df.tip.max())
    y_data = m*x_data + b
    right = (hv.Curve((x_data, y_data), x, y)
             * hv.Scatter((df[x], df[y]), x, y))
    right.opts(opts.Scatter(
               height=400, width=400, color='red', ylim=(0, 100),
               framewise=True, tools=['hover']))
    return right


tap_dmap = hv.DynamicMap(tap_histogram, streams=[posxy])

(heatmap + tap_dmap).opts(
    opts.HeatMap(tools=['tap', 'hover'],
                 height=400, width=400, toolbar='above'),
    opts.Curve(framewise=True))

Now, I wanna create a hover tool specifying the different parameters on the dependent plot. So far I am only being able to use the default hover (.opts(tools['hover'])) as in the code above. When I try to build a custom hover to dynamically change the fields based on x and y streamed values, it does not update the hover after tapping on the heatmap. It only keeps the initial values of x and y.

Here's an example of my current code:

Try to tap in total_bil x size, for example.

import pandas as pd
import numpy as np
import holoviews as hv
import seaborn as sns
from holoviews import opts
from bokeh.models import HoverTool

hv.extension('bokeh', width=90)

# Declare dataset
df = sns.load_dataset('tips')
df = df[['total_bill', 'tip', 'size']]

# Declare HeatMap
corr = df.corr()
heatmap = hv.HeatMap((corr.columns, corr.index, corr))

# Declare Tap stream with heatmap as source and initial values
posxy = hv.streams.Tap(source=heatmap, x='total_bill', y='tip')

# Define function to compute histogram based on tap location
def tap_histogram(x, y):
    m, b = np.polyfit(df[x], df[y], deg=1)
    x_data = np.linspace(df.tip.min(), df.tip.max())
    y_data = m*x_data + b
    right = (hv.Curve((x_data, y_data), x, y)
             * hv.Scatter((df[x], df[y]), x, y))

    tooltips = [(x, '@'+x),
                (y, '@'+y)
               ]
    hover = HoverTool(tooltips=tooltips)
    right.opts(opts.Scatter(
               height=400, width=400, color='red', ylim=(0, 100),
               framewise=True, tools=[hover]))
    return right


tap_dmap = hv.DynamicMap(tap_histogram, streams=[posxy])

(heatmap + tap_dmap).opts(
    opts.HeatMap(tools=['tap', 'hover'],
                 height=400, width=400, toolbar='above'),
    opts.Curve(framewise=True))
Daniel Lima
  • 925
  • 1
  • 8
  • 22

0 Answers0