mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-23 12:12:59 -05:00
Update panel examples to panel 0.13.1 (#458)
* Update panel examples to panel 0.13.1 * More indent
This commit is contained in:
@@ -6,30 +6,27 @@
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.13.0-rc.10/dist/panel.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.13.1/dist/panel.min.js"></script>
|
||||
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
|
||||
</head>
|
||||
<py-env>
|
||||
- bokeh
|
||||
- numpy
|
||||
- panel==0.13.1
|
||||
</py-env>
|
||||
<body>
|
||||
<py-env>
|
||||
- bokeh
|
||||
- numpy
|
||||
- panel==0.13.1a2
|
||||
</py-env>
|
||||
<h1>Panel Example</h1>
|
||||
<div id="myplot"></div>
|
||||
<div id="simple_app"></div>
|
||||
<py-script>
|
||||
import asyncio
|
||||
import panel as pn
|
||||
import panel as pn
|
||||
|
||||
slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude')
|
||||
slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude')
|
||||
|
||||
def callback(new):
|
||||
return f'Amplitude is: {new}'
|
||||
def callback(new):
|
||||
return f'Amplitude is: {new}'
|
||||
|
||||
row = pn.Row(slider, pn.bind(callback, slider))
|
||||
|
||||
await pn.io.pyodide.show(row, 'myplot')
|
||||
pn.Row(slider, pn.bind(callback, slider)).servable(target='simple_app');
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/markdown.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript" src="https://unpkg.com/h3-js@3.7.2/dist/h3-js.umd.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/deck.gl@8.6.7/dist.min.js"></script>
|
||||
@@ -25,30 +25,32 @@
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/defaulttheme/default.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<style>
|
||||
#sidebar {
|
||||
width: 400px;
|
||||
width: 400px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
|
||||
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<py-env>
|
||||
- bokeh
|
||||
- numpy
|
||||
- pandas
|
||||
- panel==0.13.1a2
|
||||
</py-env>
|
||||
|
||||
<py-env>
|
||||
- bokeh
|
||||
- numpy
|
||||
- pandas
|
||||
- panel==0.13.1
|
||||
</py-env>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid d-flex flex-column vh-100 overflow-hidden" id="container">
|
||||
<nav class="navbar navbar-expand-md navbar-dark sticky-top shadow" id="header" style="background-color: #000000;">
|
||||
<button type="button" class="navbar-toggle collapsed" id="sidebarCollapse">
|
||||
@@ -59,167 +61,162 @@
|
||||
<img src="./logo.png" class="app-logo">
|
||||
</a>
|
||||
<a class="title" href="" style="color: #f0ab3c;">Panel DeckGL NYC Taxi Demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row overflow-hidden" id="content">
|
||||
<div class="d-flex flex-nowrap" id="content">
|
||||
<div class="sidenav" id="sidebar">
|
||||
<ul class="nav flex-column">
|
||||
<div class="bk-root" id="widgets"></div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
<ul class="nav flex-column" >
|
||||
<div class="bk-root" id="widgets"></div>
|
||||
<py-repl id="my-repl" auto-generate="true"> </py-repl>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col mh-100 float-left" style="padding: 0;">
|
||||
<div class="col mh-100" style="padding: 0">
|
||||
<div class="bk-root" id="plot"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<py-script>
|
||||
import asyncio
|
||||
import panel as pn
|
||||
import pandas as pd
|
||||
import param
|
||||
|
||||
import panel as pn
|
||||
import param
|
||||
import pandas as pd
|
||||
from pyodide.http import open_url
|
||||
|
||||
from panel.io.pyodide import show
|
||||
from pyodide.http import open_url
|
||||
MAPBOX_KEY = "pk.eyJ1IjoicGFuZWxvcmciLCJhIjoiY2s1enA3ejhyMWhmZjNobjM1NXhtbWRrMyJ9.B_frQsAVepGIe-HiOJeqvQ"
|
||||
|
||||
MAPBOX_KEY = "pk.eyJ1IjoicGFuZWxvcmciLCJhIjoiY2s1enA3ejhyMWhmZjNobjM1NXhtbWRrMyJ9.B_frQsAVepGIe-HiOJeqvQ"
|
||||
class App(param.Parameterized):
|
||||
|
||||
class App(pn.viewable.Viewer):
|
||||
data = param.DataFrame(precedence=-1)
|
||||
|
||||
data = param.DataFrame(precedence=-1)
|
||||
view = param.DataFrame(precedence=-1)
|
||||
|
||||
view = param.DataFrame(precedence=-1)
|
||||
arc_view = param.DataFrame(precedence=-1)
|
||||
|
||||
arc_view = param.DataFrame(precedence=-1)
|
||||
radius = param.Integer(default=50, bounds=(20, 1000))
|
||||
|
||||
radius = param.Integer(default=50, bounds=(20, 1000))
|
||||
elevation = param.Integer(default=10, bounds=(0, 50))
|
||||
|
||||
elevation = param.Integer(default=10, bounds=(0, 50))
|
||||
hour = param.Integer(default=0, bounds=(0, 23))
|
||||
|
||||
hour = param.Integer(default=0, bounds=(0, 23))
|
||||
speed = param.Integer(default=1, bounds=(0, 10), precedence=-1)
|
||||
|
||||
speed = param.Integer(default=1, bounds=(0, 10), precedence=-1)
|
||||
play = param.Event(label='▷')
|
||||
|
||||
play = param.Event(label='▷')
|
||||
def __init__(self, **params):
|
||||
self.deck_gl = None
|
||||
super().__init__(**params)
|
||||
self.deck_gl = pn.pane.DeckGL(
|
||||
dict(self.spec),
|
||||
mapbox_api_key=MAPBOX_KEY,
|
||||
throttle={'click': 10},
|
||||
sizing_mode='stretch_both',
|
||||
margin=0
|
||||
)
|
||||
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
||||
self._playing = False
|
||||
self._cb = pn.state.add_periodic_callback(
|
||||
self._update_hour, 1000//self.speed, start=False
|
||||
)
|
||||
|
||||
def __init__(self, **params):
|
||||
self.deck_gl = None
|
||||
super().__init__(**params)
|
||||
self.deck_gl = pn.pane.DeckGL(
|
||||
dict(self.spec),
|
||||
mapbox_api_key=MAPBOX_KEY,
|
||||
throttle={'click': 10},
|
||||
sizing_mode='stretch_both',
|
||||
margin=0
|
||||
)
|
||||
self.deck_gl.param.watch(self._update_arc_view, 'click_state')
|
||||
self._playing = False
|
||||
self._cb = pn.state.add_periodic_callback(
|
||||
self._update_hour, 1000//self.speed, start=False
|
||||
)
|
||||
@property
|
||||
def spec(self):
|
||||
return {
|
||||
"initialViewState": {
|
||||
"bearing": 0,
|
||||
"latitude": 40.7,
|
||||
"longitude": -73.9,
|
||||
"maxZoom": 15,
|
||||
"minZoom": 5,
|
||||
"pitch": 40.5,
|
||||
"zoom": 11
|
||||
},
|
||||
"layers": [self.hex_layer, self.arc_layer],
|
||||
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
||||
"views": [
|
||||
{"@@type": "MapView", "controller": True}
|
||||
]
|
||||
}
|
||||
|
||||
def __panel__(self):
|
||||
return self.deck_gl
|
||||
@property
|
||||
def hex_layer(self):
|
||||
return {
|
||||
"@@type": "HexagonLayer",
|
||||
"autoHighlight": True,
|
||||
"coverage": 1,
|
||||
"data": self.data if self.view is None else self.view,
|
||||
"elevationRange": [0, 100],
|
||||
"elevationScale": self.elevation,
|
||||
"radius": self.radius,
|
||||
"extruded": True,
|
||||
"getPosition": "@@=[pickup_x, pickup_y]",
|
||||
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
||||
}
|
||||
|
||||
@property
|
||||
def spec(self):
|
||||
return {
|
||||
"initialViewState": {
|
||||
"bearing": 0,
|
||||
"latitude": 40.7,
|
||||
"longitude": -73.9,
|
||||
"maxZoom": 15,
|
||||
"minZoom": 5,
|
||||
"pitch": 40.5,
|
||||
"zoom": 11
|
||||
},
|
||||
"layers": [self.hex_layer, self.arc_layer],
|
||||
"mapStyle": "mapbox://styles/mapbox/dark-v9",
|
||||
"views": [
|
||||
{"@@type": "MapView", "controller": True}
|
||||
]
|
||||
}
|
||||
@property
|
||||
def arc_layer(self):
|
||||
return {
|
||||
"@@type": "ArcLayer",
|
||||
"id": 'arc-layer',
|
||||
"data": self.arc_view,
|
||||
"pickable": True,
|
||||
"getWidth": 1,
|
||||
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
||||
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
||||
"getSourceColor": [0, 255, 0, 180],
|
||||
"getTargetColor": [240, 100, 0, 180]
|
||||
}
|
||||
|
||||
@property
|
||||
def hex_layer(self):
|
||||
return {
|
||||
"@@type": "HexagonLayer",
|
||||
"autoHighlight": True,
|
||||
"coverage": 1,
|
||||
"data": self.data if self.view is None else self.view,
|
||||
"elevationRange": [0, 100],
|
||||
"elevationScale": self.elevation,
|
||||
"radius": self.radius,
|
||||
"extruded": True,
|
||||
"getPosition": "@@=[pickup_x, pickup_y]",
|
||||
"id": "8a553b25-ef3a-489c-bbe2-e102d18a3211"
|
||||
}
|
||||
def _update_hour(self):
|
||||
self.hour = (self.hour+1) % 24
|
||||
|
||||
@property
|
||||
def arc_layer(self):
|
||||
return {
|
||||
"@@type": "ArcLayer",
|
||||
"id": 'arc-layer',
|
||||
"data": self.arc_view,
|
||||
"pickable": True,
|
||||
"getWidth": 1,
|
||||
"getSourcePosition": "@@=[pickup_x, pickup_y]",
|
||||
"getTargetPosition": "@@=[dropoff_x, dropoff_y]",
|
||||
"getSourceColor": [0, 255, 0, 180],
|
||||
"getTargetColor": [240, 100, 0, 180]
|
||||
}
|
||||
@param.depends('view', watch=True)
|
||||
def _update_arc_view(self, event=None):
|
||||
data = self.data if self.view is None else self.view
|
||||
if not self.deck_gl or not self.deck_gl.click_state:
|
||||
self.arc_view = data.iloc[:0]
|
||||
return
|
||||
lon, lat = self.deck_gl.click_state['coordinate']
|
||||
tol = 0.001
|
||||
self.arc_view = data[
|
||||
(df.pickup_x>=float(lon-tol)) &
|
||||
(df.pickup_x<=float(lon+tol)) &
|
||||
(df.pickup_y>=float(lat-tol)) &
|
||||
(df.pickup_y<=float(lat+tol))
|
||||
]
|
||||
|
||||
def _update_hour(self):
|
||||
self.hour = (self.hour+1) % 24
|
||||
@param.depends('hour', watch=True, on_init=True)
|
||||
def _update_hourly_view(self):
|
||||
self.view = self.data[self.data.hour==self.hour]
|
||||
|
||||
@param.depends('view', watch=True)
|
||||
def _update_arc_view(self, event=None):
|
||||
data = self.data if self.view is None else self.view
|
||||
if not self.deck_gl or not self.deck_gl.click_state:
|
||||
self.arc_view = data.iloc[:0]
|
||||
else:
|
||||
lon, lat = self.deck_gl.click_state['coordinate']
|
||||
tol = 0.001
|
||||
self.arc_view = data[
|
||||
(df.pickup_x>=float(lon-tol)) &
|
||||
(df.pickup_x<=float(lon+tol)) &
|
||||
(df.pickup_y>=float(lat-tol)) &
|
||||
(df.pickup_y<=float(lat+tol))
|
||||
]
|
||||
@param.depends('speed', watch=True)
|
||||
def _update_speed(self):
|
||||
self._cb.period = 1000//self.speed
|
||||
|
||||
@param.depends('hour', watch=True, on_init=True)
|
||||
def _update_hourly_view(self):
|
||||
self.view = self.data[self.data.hour==self.hour]
|
||||
@param.depends('play', watch=True)
|
||||
def _play_pause(self):
|
||||
if self._playing:
|
||||
self._cb.stop()
|
||||
self.param.play.label = '▷'
|
||||
self.param.speed.precedence = -1
|
||||
else:
|
||||
self._cb.start()
|
||||
self.param.play.label = '❚❚'
|
||||
self.param.speed.precedence = 1
|
||||
self._playing = not self._playing
|
||||
|
||||
@param.depends('speed', watch=True)
|
||||
def _update_speed(self):
|
||||
self._cb.period = 1000//self.speed
|
||||
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
||||
def update_spec(self):
|
||||
self.deck_gl.object = dict(self.spec)
|
||||
|
||||
@param.depends('play', watch=True)
|
||||
def _play_pause(self):
|
||||
if self._playing:
|
||||
self._cb.stop()
|
||||
self.param.play.label = '▷'
|
||||
self.param.speed.precedence = -1
|
||||
else:
|
||||
self._cb.start()
|
||||
self.param.play.label = '❚❚'
|
||||
self.param.speed.precedence = 1
|
||||
self._playing = not self._playing
|
||||
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
||||
df = pd.read_csv(open_url(url))
|
||||
app = App(data=df)
|
||||
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
||||
|
||||
@param.depends('view', 'radius', 'elevation', 'arc_view', watch=True)
|
||||
def update_spec(self):
|
||||
self.deck_gl.object = dict(self.spec)
|
||||
|
||||
url = 'https://s3.eu-west-1.amazonaws.com/assets.holoviews.org/data/nyc_taxi_wide.csv'
|
||||
df = pd.read_csv(open_url(url))
|
||||
app = App(data=df)
|
||||
controls = pn.Param(app.param, sizing_mode='stretch_width', show_name=False)
|
||||
|
||||
await show(controls, 'widgets')
|
||||
await show(app, 'plot')
|
||||
app.deck_gl.servable(target='plot')
|
||||
controls.servable(target='widgets');
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/markdown.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
|
||||
@@ -22,14 +22,14 @@
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/defaulttheme/default.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
|
||||
<style>
|
||||
#sidebar {
|
||||
@@ -49,7 +49,7 @@
|
||||
- numpy
|
||||
- pandas
|
||||
- scikit-learn
|
||||
- panel==0.13.1a2
|
||||
- panel==0.13.1
|
||||
</py-env>
|
||||
|
||||
<body>
|
||||
@@ -81,99 +81,92 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<py-script>
|
||||
import asyncio
|
||||
import altair as alt
|
||||
import panel as pn
|
||||
import pandas as pd
|
||||
|
||||
import altair as alt
|
||||
import panel as pn
|
||||
import pandas as pd
|
||||
from sklearn.cluster import KMeans
|
||||
from pyodide.http import open_url
|
||||
|
||||
from panel.io.pyodide import show
|
||||
from sklearn.cluster import KMeans
|
||||
from pyodide.http import open_url
|
||||
pn.config.sizing_mode = 'stretch_width'
|
||||
|
||||
pn.config.sizing_mode = 'stretch_width'
|
||||
url = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv'
|
||||
penguins = pd.read_csv(open_url(url)).dropna()
|
||||
cols = list(penguins.columns)[2:6]
|
||||
|
||||
url = 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv'
|
||||
penguins = pd.read_csv(open_url(url)).dropna()
|
||||
cols = list(penguins.columns)[2:6]
|
||||
x = pn.widgets.Select(name='x', options=cols, value='bill_depth_mm').servable(target='x-widget')
|
||||
y = pn.widgets.Select(name='y', options=cols, value='bill_length_mm').servable(target='y-widget')
|
||||
n_clusters = pn.widgets.IntSlider(name='n_clusters', start=1, end=5, value=3).servable(target='n-widget')
|
||||
|
||||
x = pn.widgets.Select(name='x', options=cols, value='bill_depth_mm')
|
||||
y = pn.widgets.Select(name='y', options=cols, value='bill_length_mm')
|
||||
n_clusters = pn.widgets.IntSlider(name='n_clusters', start=1, end=5, value=3)
|
||||
brush = alt.selection_interval(name='brush') # selection of type "interval"
|
||||
|
||||
brush = alt.selection_interval(name='brush') # selection of type "interval"
|
||||
def get_clusters(n_clusters):
|
||||
kmeans = KMeans(n_clusters=n_clusters)
|
||||
est = kmeans.fit(penguins[cols].values)
|
||||
df = penguins.copy()
|
||||
df['labels'] = est.labels_.astype('str')
|
||||
return df
|
||||
|
||||
def get_clusters(n_clusters):
|
||||
kmeans = KMeans(n_clusters=n_clusters)
|
||||
est = kmeans.fit(penguins[cols].values)
|
||||
df = penguins.copy()
|
||||
df['labels'] = est.labels_.astype('str')
|
||||
return df
|
||||
def get_chart(x, y, df):
|
||||
centers = df.groupby('labels').mean()
|
||||
return (
|
||||
alt.Chart(df)
|
||||
.mark_point(size=100)
|
||||
.encode(
|
||||
x=alt.X(x, scale=alt.Scale(zero=False)),
|
||||
y=alt.Y(y, scale=alt.Scale(zero=False)),
|
||||
shape='labels',
|
||||
color='species'
|
||||
).add_selection(brush).properties(width=800) +
|
||||
alt.Chart(centers)
|
||||
.mark_point(size=250, shape='cross', color='black')
|
||||
.encode(x=x+':Q', y=y+':Q')
|
||||
)
|
||||
|
||||
def get_chart(x, y, df):
|
||||
centers = df.groupby('labels').mean()
|
||||
return (alt.Chart(df)
|
||||
.mark_point(size=100)
|
||||
.encode(
|
||||
x=alt.X(x, scale=alt.Scale(zero=False)),
|
||||
y=alt.Y(y, scale=alt.Scale(zero=False)),
|
||||
shape='labels',
|
||||
color='species'
|
||||
).add_selection(brush).properties(width=800) +
|
||||
alt.Chart(centers)
|
||||
.mark_point(size=250, shape='cross', color='black')
|
||||
.encode(x=x+':Q', y=y+':Q')
|
||||
)
|
||||
intro = pn.pane.Markdown("""
|
||||
This app provides an example of **building a simple dashboard using
|
||||
Panel**.\n\nIt demonstrates how to take the output of **k-means
|
||||
clustering on the Penguins dataset** using scikit-learn,
|
||||
parameterizing the number of clusters and the variables to
|
||||
plot.\n\nThe plot and the table are linked, i.e. selecting on the plot
|
||||
will filter the data in the table.\n\n The **`x` marks the center** of
|
||||
the cluster.
|
||||
""").servable(target='intro')
|
||||
|
||||
chart = pn.pane.Vega()
|
||||
table = pn.widgets.Tabulator(pagination='remote', page_size=10)
|
||||
chart = pn.pane.Vega().servable(target='cluster-plot')
|
||||
table = pn.widgets.Tabulator(pagination='remote', page_size=10).servable(target='table')
|
||||
|
||||
def update_table(event=None):
|
||||
table.value = get_clusters(n_clusters.value)
|
||||
def update_table(event=None):
|
||||
table.value = get_clusters(n_clusters.value)
|
||||
|
||||
n_clusters.param.watch(update_table, 'value')
|
||||
n_clusters.param.watch(update_table, 'value')
|
||||
|
||||
@pn.depends(x, y, n_clusters, watch=True)
|
||||
def update_chart(*events):
|
||||
chart.object = get_chart(x.value, y.value, table.value)
|
||||
chart.selection.param.watch(update_filters, 'brush')
|
||||
@pn.depends(x, y, n_clusters, watch=True)
|
||||
def update_chart(*events):
|
||||
chart.object = get_chart(x.value, y.value, table.value)
|
||||
chart.selection.param.watch(update_filters, 'brush')
|
||||
|
||||
def update_filters(event=None):
|
||||
filters = []
|
||||
for k, v in (getattr(event, 'new') or {}).items():
|
||||
filters.append(dict(field=k, type='>=', value=v[0]))
|
||||
filters.append(dict(field=k, type='<=', value=v[1]))
|
||||
table.filters = filters
|
||||
def update_filters(event=None):
|
||||
filters = []
|
||||
for k, v in (getattr(event, 'new') or {}).items():
|
||||
filters.append(dict(field=k, type='>=', value=v[0]))
|
||||
filters.append(dict(field=k, type='<=', value=v[1]))
|
||||
table.filters = filters
|
||||
|
||||
update_table()
|
||||
update_chart()
|
||||
|
||||
intro = """
|
||||
This app provides an example of **building a simple dashboard using
|
||||
Panel**.\n\nIt demonstrates how to take the output of **k-means
|
||||
clustering on the Penguins dataset** using scikit-learn,
|
||||
parameterizing the number of clusters and the variables to
|
||||
plot.\n\nThe plot and the table are linked, i.e. selecting on the plot
|
||||
will filter the data in the table.\n\n The **`x` marks the center** of
|
||||
the cluster.
|
||||
"""
|
||||
|
||||
await show(x, 'x-widget')
|
||||
await show(y, 'y-widget')
|
||||
await show(n_clusters, 'n-widget')
|
||||
await show(intro, 'intro')
|
||||
await show(chart, 'cluster-plot')
|
||||
await show(table, 'table')
|
||||
update_table()
|
||||
update_chart()
|
||||
</py-script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('#sidebarCollapse').on('click', function () {
|
||||
$('#sidebar').toggleClass('active')
|
||||
$(this).toggleClass('active')
|
||||
var interval = setInterval(function () { window.dispatchEvent(new Event('resize')); }, 10);
|
||||
setTimeout(function () { clearInterval(interval) }, 210)
|
||||
});
|
||||
$('#sidebarCollapse').on('click', function () {
|
||||
$('#sidebar').toggleClass('active')
|
||||
$(this).toggleClass('active')
|
||||
var interval = setInterval(function () { window.dispatchEvent(new Event('resize')); }, 10);
|
||||
setTimeout(function () { clearInterval(interval) }, 210)
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -12,21 +12,21 @@
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.ico">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/css/markdown.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
Bokeh.set_log_level("info");
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.0/dist/bundled/defaulttheme/default.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/bootstraptemplate/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@holoviz/panel@0.13.1/dist/bundled/defaulttheme/default.css">
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
|
||||
@@ -36,10 +36,10 @@
|
||||
</head>
|
||||
|
||||
<py-env>
|
||||
- bokeh
|
||||
- numpy
|
||||
- pandas
|
||||
- panel
|
||||
- bokeh
|
||||
- numpy
|
||||
- pandas
|
||||
- panel==0.13.1
|
||||
</py-env>
|
||||
|
||||
<body>
|
||||
@@ -66,58 +66,53 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<py-script>
|
||||
import asyncio
|
||||
import panel as pn
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
import panel as pn
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from bokeh.models import ColumnDataSource
|
||||
from bokeh.plotting import figure
|
||||
|
||||
from bokeh.models import ColumnDataSource
|
||||
from bokeh.plotting import figure
|
||||
from panel.io.pyodide import show
|
||||
df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')).cumsum()
|
||||
|
||||
df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')).cumsum()
|
||||
rollover = pn.widgets.IntInput(name='Rollover', value=15)
|
||||
follow = pn.widgets.Checkbox(name='Follow', value=True, align='end')
|
||||
|
||||
rollover = pn.widgets.IntInput(name='Rollover', value=15)
|
||||
follow = pn.widgets.Checkbox(name='Follow', value=True, align='end')
|
||||
tabulator = pn.widgets.Tabulator(df, height=450, width=400).servable(target='table')
|
||||
|
||||
tabulator = pn.widgets.Tabulator(df, height=450, width=400)
|
||||
def color_negative_red(val):
|
||||
"""
|
||||
Takes a scalar and returns a string with
|
||||
the css property `'color: red'` for negative
|
||||
strings, black otherwise.
|
||||
"""
|
||||
color = 'red' if val < 0 else 'green'
|
||||
return 'color: %s' % color
|
||||
|
||||
def color_negative_red(val):
|
||||
"""
|
||||
Takes a scalar and returns a string with
|
||||
the css property `'color: red'` for negative
|
||||
strings, black otherwise.
|
||||
"""
|
||||
color = 'red' if val < 0 else 'green'
|
||||
return 'color: %s' % color
|
||||
tabulator.style.applymap(color_negative_red)
|
||||
|
||||
tabulator.style.applymap(color_negative_red)
|
||||
p = figure(height=450, width=600)
|
||||
|
||||
p = figure(height=450, width=600)
|
||||
cds = ColumnDataSource(data=ColumnDataSource.from_df(df))
|
||||
|
||||
cds = ColumnDataSource(data=ColumnDataSource.from_df(df))
|
||||
p.line('index', 'A', source=cds, line_color='red')
|
||||
p.line('index', 'B', source=cds, line_color='green')
|
||||
p.line('index', 'C', source=cds, line_color='blue')
|
||||
p.line('index', 'D', source=cds, line_color='purple')
|
||||
|
||||
p.line('index', 'A', source=cds, line_color='red')
|
||||
p.line('index', 'B', source=cds, line_color='green')
|
||||
p.line('index', 'C', source=cds, line_color='blue')
|
||||
p.line('index', 'D', source=cds, line_color='purple')
|
||||
def stream():
|
||||
data = df.iloc[-1] + np.random.randn(4)
|
||||
tabulator.stream(data, rollover=rollover.value, follow=follow.value)
|
||||
value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()}
|
||||
value['index'] = [tabulator.value.index[-1]]
|
||||
cds.stream(value)
|
||||
|
||||
def stream():
|
||||
data = df.iloc[-1] + np.random.randn(4)
|
||||
tabulator.stream(data, rollover=rollover.value, follow=follow.value)
|
||||
value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()}
|
||||
value['index'] = [tabulator.value.index[-1]]
|
||||
cds.stream(value)
|
||||
cb = pn.state.add_periodic_callback(stream, 200)
|
||||
|
||||
cb = pn.state.add_periodic_callback(stream, 200)
|
||||
|
||||
controls = pn.Row(cb.param.period, rollover, follow, width=400)
|
||||
|
||||
await show(controls, 'controls')
|
||||
await show(tabulator, 'table')
|
||||
await show(p, 'plot')
|
||||
pn.pane.Bokeh(p).servable(target='plot')
|
||||
pn.Row(cb.param.period, rollover, follow, width=400).servable(target='controls')
|
||||
</py-script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user