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))