Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • grosch1/jupyter-dashboarding
  • petrova1/jupyter-dashboarding
2 results
Show changes
%% Cell type:markdown id: tags:
# Usage
Start voila with the gridstack template. If `show_handles` is set to True, you can drag the individual dashboard items around.
```
voila --template=gridstack --VoilaConfiguration.resources='{"gridstack": {"show_handles": True}}' ./dashboards/gridstack-scotch.ipynb
```
%% Cell type:markdown id: tags:
# Got Scotch?
%% Cell type:markdown id: tags:
In this notebook, we're going to create a dashboard that recommends scotches based on their taste profiles.
%% Cell type:code id: tags:
``` python
%matplotlib widget
```
%% Cell type:code id: tags:
``` python
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import os
```
%% Cell type:code id: tags:
``` python
import ipywidgets as widgets
from traitlets import Unicode, List, Instance, link, HasTraits
from IPython.display import display, clear_output, HTML, Javascript
```
%% Cell type:code id: tags:
``` python
display(widgets.Button())
```
%% Output
%% Cell type:markdown id: tags:
## Load Data <span style="float: right; font-size: 0.5em"><a href="#Got-Scotch?">Top</a></span>
%% Cell type:code id: tags:
``` python
features = [[2, 2, 2, 0, 0, 2, 1, 2, 2, 2, 2, 2],
[3, 3, 1, 0, 0, 4, 3, 2, 2, 3, 3, 2],
[1, 3, 2, 0, 0, 2, 0, 0, 2, 2, 3, 1],
[4, 1, 4, 4, 0, 0, 2, 0, 1, 2, 1, 0],
[2, 2, 2, 0, 0, 1, 1, 1, 2, 3, 1, 3],
[2, 3, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
[0, 2, 0, 0, 0, 1, 1, 0, 2, 2, 3, 1],
[2, 3, 1, 0, 0, 2, 1, 2, 2, 2, 2, 2],
[2, 2, 1, 0, 0, 1, 0, 0, 2, 2, 2, 1],
[2, 3, 2, 1, 0, 0, 2, 0, 2, 1, 2, 3],
[4, 3, 2, 0, 0, 2, 1, 3, 3, 0, 1, 2],
[3, 2, 1, 0, 0, 3, 2, 1, 0, 2, 2, 2],
[4, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2],
[2, 2, 1, 0, 0, 2, 2, 0, 0, 2, 3, 1],
[3, 2, 2, 0, 0, 3, 1, 1, 2, 3, 2, 2],
[2, 2, 2, 0, 0, 2, 2, 1, 2, 2, 2, 2],
[1, 2, 1, 0, 0, 0, 1, 1, 0, 2, 2, 1],
[2, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2],
[2, 2, 3, 1, 0, 2, 2, 1, 1, 1, 1, 3],
[1, 1, 2, 2, 0, 2, 2, 1, 2, 2, 2, 3],
[1, 2, 1, 1, 0, 1, 1, 1, 1, 2, 2, 1],
[3, 1, 4, 2, 1, 0, 2, 0, 2, 1, 1, 0],
[1, 3, 1, 0, 0, 1, 1, 0, 2, 2, 2, 1],
[3, 2, 3, 3, 1, 0, 2, 0, 1, 1, 2, 0],
[2, 2, 2, 0, 1, 2, 2, 1, 2, 2, 1, 2],
[2, 3, 2, 1, 0, 0, 1, 0, 2, 2, 2, 1],
[4, 2, 2, 0, 0, 1, 2, 2, 2, 2, 2, 2],
[3, 2, 2, 1, 0, 1, 2, 2, 1, 2, 3, 2],
[2, 2, 2, 0, 0, 2, 1, 0, 1, 2, 2, 1],
[2, 2, 1, 0, 0, 2, 1, 1, 1, 3, 2, 2],
[2, 3, 1, 1, 0, 0, 0, 0, 1, 2, 2, 1],
[2, 3, 1, 0, 0, 2, 1, 1, 4, 2, 2, 2],
[2, 3, 1, 1, 1, 1, 1, 2, 0, 2, 0, 3],
[2, 3, 1, 0, 0, 2, 1, 1, 1, 1, 2, 1],
[2, 1, 3, 0, 0, 0, 3, 1, 0, 2, 2, 3],
[1, 2, 0, 0, 0, 1, 0, 1, 2, 1, 2, 1],
[2, 3, 1, 0, 0, 1, 2, 1, 2, 1, 2, 2],
[1, 2, 1, 0, 0, 1, 2, 1, 2, 2, 2, 1],
[3, 2, 1, 0, 0, 1, 2, 1, 1, 2, 2, 2],
[2, 2, 2, 2, 0, 1, 0, 1, 2, 2, 1, 3],
[1, 3, 1, 0, 0, 0, 1, 1, 1, 2, 0, 1],
[1, 3, 1, 0, 0, 1, 1, 0, 1, 2, 2, 1],
[4, 2, 2, 0, 0, 2, 1, 4, 2, 2, 2, 2],
[3, 2, 1, 0, 0, 2, 1, 2, 1, 2, 3, 2],
[2, 4, 1, 0, 0, 1, 2, 3, 2, 3, 2, 2],
[1, 3, 1, 0, 0, 0, 0, 0, 0, 2, 2, 1],
[1, 2, 0, 0, 0, 1, 1, 1, 2, 2, 3, 1],
[1, 2, 1, 0, 0, 1, 2, 0, 0, 2, 2, 1],
[2, 3, 1, 0, 0, 2, 2, 2, 1, 2, 2, 2],
[1, 2, 1, 0, 0, 1, 2, 0, 1, 2, 2, 1],
[2, 2, 1, 1, 0, 1, 2, 0, 2, 1, 2, 1],
[2, 3, 1, 0, 0, 1, 1, 2, 1, 2, 2, 2],
[2, 3, 1, 0, 0, 2, 2, 2, 2, 2, 1, 2],
[2, 2, 3, 1, 0, 2, 1, 1, 1, 2, 1, 3],
[1, 3, 1, 1, 0, 2, 2, 0, 1, 2, 1, 1],
[2, 1, 2, 2, 0, 1, 1, 0, 2, 1, 1, 3],
[2, 3, 1, 0, 0, 2, 2, 1, 2, 1, 2, 2],
[4, 1, 4, 4, 1, 0, 1, 2, 1, 1, 1, 0],
[4, 2, 4, 4, 1, 0, 0, 1, 1, 1, 0, 0],
[2, 3, 1, 0, 0, 1, 1, 2, 0, 1, 3, 1],
[1, 1, 1, 1, 0, 1, 1, 0, 1, 2, 1, 1],
[3, 2, 1, 0, 0, 1, 1, 1, 3, 3, 2, 2],
[4, 3, 1, 0, 0, 2, 1, 4, 2, 2, 3, 2],
[2, 1, 1, 0, 0, 1, 1, 1, 2, 1, 2, 1],
[2, 4, 1, 0, 0, 1, 0, 0, 2, 1, 1, 1],
[3, 2, 2, 0, 0, 2, 3, 3, 2, 1, 2, 2],
[2, 2, 2, 2, 0, 0, 2, 0, 2, 2, 2, 3],
[1, 2, 2, 0, 1, 2, 2, 1, 2, 3, 1, 3],
[2, 1, 2, 2, 1, 0, 1, 1, 2, 2, 2, 3],
[2, 3, 2, 1, 1, 1, 2, 1, 0, 2, 3, 1],
[3, 2, 2, 0, 0, 2, 2, 2, 2, 2, 3, 2],
[2, 2, 1, 1, 0, 2, 1, 1, 2, 2, 2, 2],
[2, 4, 1, 0, 0, 2, 1, 0, 0, 2, 1, 1],
[2, 2, 1, 0, 0, 1, 0, 1, 2, 2, 2, 1],
[2, 2, 2, 2, 0, 2, 2, 1, 2, 1, 0, 3],
[2, 2, 1, 0, 0, 2, 2, 2, 3, 3, 3, 2],
[2, 3, 1, 0, 0, 0, 2, 0, 2, 1, 3, 1],
[4, 2, 3, 3, 0, 1, 3, 0, 1, 2, 2, 0],
[1, 2, 1, 0, 0, 2, 0, 1, 1, 2, 2, 1],
[1, 3, 2, 0, 0, 0, 2, 0, 2, 1, 2, 1],
[2, 2, 2, 1, 0, 0, 2, 0, 0, 0, 2, 3],
[1, 1, 1, 0, 0, 1, 0, 0, 1, 2, 2, 1],
[2, 3, 2, 0, 0, 2, 2, 1, 1, 2, 0, 3],
[0, 3, 1, 0, 0, 2, 2, 1, 1, 2, 1, 1],
[2, 2, 1, 0, 0, 1, 0, 1, 2, 1, 0, 3],
[2, 3, 0, 0, 1, 0, 2, 1, 1, 2, 2, 1]]
feature_names = ['Body', 'Sweetness', 'Smoky',
'Medicinal', 'Tobacco', 'Honey',
'Spicy', 'Winey', 'Nutty',
'Malty', 'Fruity', 'cluster']
brand_names = ['Aberfeldy',
'Aberlour',
'AnCnoc',
'Ardbeg',
'Ardmore',
'ArranIsleOf',
'Auchentoshan',
'Auchroisk',
'Aultmore',
'Balblair',
'Balmenach',
'Belvenie',
'BenNevis',
'Benriach',
'Benrinnes',
'Benromach',
'Bladnoch',
'BlairAthol',
'Bowmore',
'Bruichladdich',
'Bunnahabhain',
'Caol Ila',
'Cardhu',
'Clynelish',
'Craigallechie',
'Craigganmore',
'Dailuaine',
'Dalmore',
'Dalwhinnie',
'Deanston',
'Dufftown',
'Edradour',
'GlenDeveronMacduff',
'GlenElgin',
'GlenGarioch',
'GlenGrant',
'GlenKeith',
'GlenMoray',
'GlenOrd',
'GlenScotia',
'GlenSpey',
'Glenallachie',
'Glendronach',
'Glendullan',
'Glenfarclas',
'Glenfiddich',
'Glengoyne',
'Glenkinchie',
'Glenlivet',
'Glenlossie',
'Glenmorangie',
'Glenrothes',
'Glenturret',
'Highland Park',
'Inchgower',
'Isle of Jura',
'Knochando',
'Lagavulin',
'Laphroig',
'Linkwood',
'Loch Lomond',
'Longmorn',
'Macallan',
'Mannochmore',
'Miltonduff',
'Mortlach',
'Oban',
'OldFettercairn',
'OldPulteney',
'RoyalBrackla',
'RoyalLochnagar',
'Scapa',
'Speyburn',
'Speyside',
'Springbank',
'Strathisla',
'Strathmill',
'Talisker',
'Tamdhu',
'Tamnavulin',
'Teaninich',
'Tobermory',
'Tomatin',
'Tomintoul',
'Tormore',
'Tullibardine']
```
%% Cell type:code id: tags:
``` python
features_df = pd.DataFrame(features, columns=feature_names, index=brand_names)
features_df = features_df.drop('cluster', axis=1)
```
%% Cell type:code id: tags:
``` python
norm = (features_df ** 2).sum(axis=1).apply('sqrt')
normed_df = features_df.divide(norm, axis=0)
sim_df = normed_df.dot(normed_df.T)
```
%% Cell type:code id: tags:
``` python
def radar(df, ax=None):
# calculate evenly-spaced axis angles
num_vars = len(df.columns)
theta = 2*np.pi * np.linspace(0, 1-1./num_vars, num_vars)
# rotate theta such that the first axis is at the top
theta += np.pi/2
if not ax:
fig = plt.figure(figsize=(4, 4))
ax = fig.add_subplot(1,1,1, projection='polar')
else:
ax.clear()
for d, color in zip(df.itertuples(), sns.color_palette()):
ax.plot(theta, d[1:], color=color, alpha=0.7)
ax.fill(theta, d[1:], facecolor=color, alpha=0.5)
ax.set_xticklabels(df.columns)
legend = ax.legend(df.index, loc=(0.9, .95))
return ax
```
%% Cell type:code id: tags:
``` python
```
%% Cell type:code id: tags:
``` python
class RadarWidget(HasTraits):
factors_keys = List(['Aberfeldy'])
def __init__(self, df, **kwargs):
self.df = df
super(RadarWidget, self).__init__(**kwargs)
self.ax = None
self.factors_keys_changed()
def factors_keys_changed(self):
new_value = self.factors_keys
if self.ax:
self.ax.clear()
self.ax = radar(self.df.loc[new_value], self.ax)
```
%% Cell type:markdown id: tags:
We now define a *get_similar( )* function to return the data of the top n similar scotches to a given scotch.
%% Cell type:code id: tags:
``` python
def get_similar(name, n, top=True):
a = sim_df[name].sort_values(ascending=False)
a.name = 'Similarity'
df = pd.DataFrame(a) #.join(features_df).iloc[start:end]
return df.head(n) if top else df.tail(n)
```
%% Cell type:markdown id: tags:
We also need a function *on_pick_scotch* that will display a table of the top 5 similar scotches that Radar View watches, based on a given selected Scotch.
%% Cell type:code id: tags:
``` python
def on_pick_scotch(Scotch):
name = Scotch
# Get top 6 similar whiskeys, and remove this one
top_df = get_similar(name, 6).iloc[1:]
# Get bottom 5 similar whiskeys
df = top_df
# Make table index a set of links that the radar widget will watch
df.index = ['''<a class="scotch" href="#" data-factors_keys='["{}","{}"]'>{}</a>'''.format(name, i, i) for i in df.index]
tmpl = f'''<p>If you like {name} you might want to try these five brands. Click one to see how its taste profile compares.</p>'''
prompt_w.value = tmpl
table.value = df.to_html(escape=False)
radar_w.factors_keys = [name]
plot = radar_w.factors_keys_changed()
```
%% Cell type:code id: tags:
``` python
prompt_w = widgets.HTML(value='Aberfeldy')
display(prompt_w)
```
%% Output
%% Cell type:code id: tags:
``` python
table = widgets.HTML(
value="Hello <b>World</b>"
)
display(table)
```
%% Output
%% Cell type:code id: tags:
``` python
radar_w = RadarWidget(df=features_df)
```
%% Output
%% Cell type:code id: tags:
``` python
picker_w = widgets.interact(on_pick_scotch, Scotch=list(sim_df.index))
```
%% Output
%% Cell type:code id: tags:
``` python
radar_w.factors_keys
```
%% Output
['Aberfeldy']
%% Cell type:markdown id: tags:
Powered by data from https://www.mathstat.strath.ac.uk/outreach/nessie/nessie_whisky.html and inspired by analysis from http://blog.revolutionanalytics.com/2013/12/k-means-clustering-86-single-malt-scotch-whiskies.html. This dashboard originated as a Jupyter Notebook.
%% Cell type:code id: tags:
``` python
```
%% Cell type:code id: tags:
``` python
```
......
This diff is collapsed.