\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,qe=/"
],
"text/plain": [
":Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 3,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1002"
}
},
"output_type": "execute_result"
}
],
"source": [
"df_2012 = df.loc[df['year']==2012, :].copy()\n",
"\n",
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Specification of the element type\n",
"\n",
"We used `hv.Points` to invoke an **element of visualization**. An element is just a way of converting the tabular nature of the data to a graphical representation, in this case a scatter plot of points. That is, we want to make a plot where each glyph lies in a two-dimensional plot and the values of both the x- and y-axes are independent. (This is contrasted with `hv.Scatter` in which the x-coordinate is the independent variable and the y-coordinate is dependent on x; `hv.Points` is more appropriate here.)\n",
"\n",
"The available element types may be found in the [HoloViews reference gallery](http://holoviews.org/reference/index.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Specification of dimensions\n",
"\n",
"There are two types of dimensions, **key dimensions** and **value dimensions**, specified with the `kdims` and `vdims` arguments, respectively. You can think of key and value dimensions like keys and values of a dictionary. You can think of these like key-value pairs in dictionaries (where you can have multidimensional keys). Key dimensions are indexing dimensions, which say where on the graphic the data in a row will reside. The value dimensions give information about each data point. In the simple plot above, the key dimensions are the the beak length and beak depth. Those columns determined where the glyphs were placed.\n",
"\n",
"We additionally had a value dimension, specified by `vdims`, which has additional information associated with each data point. This information was not used in the above plot, but we will put it to use momentarily."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Stylizing plots\n",
"\n",
"After a plotting Element is specified, we can stylize it using the `hv.opts` functionality. To investigate what styling options are available for each kind of plotting element, you can enter, for example\n",
"\n",
"```python\n",
"hv.help(hv.Points)\n",
"```\n",
"\n",
"and you will get detailed information on what options are available for stylizing `hv.Points` elements. Let's try a different styling for the above plot using `.opts()`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 4,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1097"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
").opts(\n",
" alpha=0.7,\n",
" color='#1f77b3',\n",
" padding=0.05,\n",
" show_grid=True,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I find the HoloViews defaults not very pleasing.\n",
"\n",
"If you agree and want to define defaults for an entire document, you may do so using `hv.opts.defaults()`. I have made some defaults that I find more pleasing that are available in the `bootcamp_utils.hv_defaults.set_defaults()` function. Let's set those defaults (which will be active for the rest of the notebook), and see how our plot looks.\n",
"\n",
"**Warning:** Setting the defaults in this way may affect some styling in more complex plots in unexpected ways."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 5,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1194"
}
},
"output_type": "execute_result"
}
],
"source": [
"bootcamp_utils.hv_defaults.set_defaults()\n",
"\n",
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Grouping by value dimensions\n",
"\n",
"Recall that we have an unused value dimension in the element we created. We would naturally like to separate out the glyphs by species. To do this, we can do a `groupby` operation on the Element. That's right, we can do groupby operations on graphical elements!"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":HoloMap [species]\n",
" :Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 6,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1291"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
").groupby(\n",
" 'species'\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now have a pull down menu to the right of the plot where we can select the species we want and the glyphs on the plot will adjust accordingly. By default, after applying the groupby operation, HoloViews gives us a HoloMap object. The column we used to group by are now selectable through a graphical interface (a pull-down menu).\n",
"\n",
"We may instead with to group by species and lay the plots out next to each other, creating a **layout**. We can use the `layout()` method do to this."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":NdLayout [species]\n",
" :Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 7,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1428"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
").groupby(\n",
" 'species'\n",
").opts(\n",
" height=275,\n",
" width=275,\n",
").layout(\n",
").opts(\n",
" \n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we may wish to **overlay** the plots for each species that we split by species."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":NdOverlay [species]\n",
" :Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 8,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1750"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
").groupby(\n",
" 'species'\n",
").overlay(\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"HoloViews was kind enough to automatically provide us with a (clickable) legend!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Further stylizing\n",
"\n",
"We can use `.opts()` to add tooltips where we can hover and get additional information from the vdims."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":NdOverlay [species]\n",
" :Points [beak length (mm),beak depth (mm)] (species)"
]
},
"execution_count": 9,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "1954"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df_2012,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species'],\n",
").groupby(\n",
" 'species'\n",
").opts(\n",
" tools=['hover']\n",
").overlay(\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As a final example of constructing this plot, let's consider the entire data set and allow the year to be selected via a HoloMap, but color by species for each year."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":HoloMap [year]\n",
" :NdOverlay [species]\n",
" :Points [beak length (mm),beak depth (mm)] (species,year)"
]
},
"execution_count": 10,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "2161"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points(\n",
" data=df,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species', 'year'],\n",
").groupby(\n",
" ['species', 'year'],\n",
").opts(\n",
" tools=['hover'],\n",
").overlay(\n",
" 'species',\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Extracting the Bokeh plotting object\n",
"\n",
"After making and displaying a HoloViews plot, we might want to get the Bokeh figure. We can extract that using `hv.render()`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" \n",
" var docs_json = {\"1b8cb8a9-ecdb-4a8e-8c6c-17e7d67e521e\":{\"roots\":{\"references\":[{\"attributes\":{\"align\":null,\"below\":[{\"id\":\"2719\"}],\"center\":[{\"id\":\"2722\"},{\"id\":\"2726\"}],\"left\":[{\"id\":\"2723\"}],\"margin\":null,\"min_border_bottom\":10,\"min_border_left\":10,\"min_border_right\":10,\"min_border_top\":10,\"plot_height\":350,\"plot_width\":450,\"renderers\":[{\"id\":\"2752\"},{\"id\":\"2760\"}],\"sizing_mode\":\"fixed\",\"title\":{\"id\":\"2711\"},\"toolbar\":{\"id\":\"2733\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"2706\"},\"x_scale\":{\"id\":\"2715\"},\"y_range\":{\"id\":\"2707\"},\"y_scale\":{\"id\":\"2717\"}},\"id\":\"2710\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data_source\":{\"id\":\"2754\"},\"glyph\":{\"id\":\"2757\"},\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2759\"},\"nonselection_glyph\":{\"id\":\"2758\"},\"selection_glyph\":null,\"view\":{\"id\":\"2761\"}},\"id\":\"2760\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"2754\"}},\"id\":\"2761\",\"type\":\"CDSView\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"2732\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"source\":{\"id\":\"2746\"}},\"id\":\"2753\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2731\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"2740\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.75},\"fill_color\":{\"value\":\"#ff7e0e\"},\"line_alpha\":{\"value\":0.75},\"line_color\":{\"value\":\"#ff7e0e\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2758\",\"type\":\"Scatter\"},{\"attributes\":{\"axis\":{\"id\":\"2723\"},\"dimension\":1,\"ticker\":{\"id\":\"2724\"}},\"id\":\"2726\",\"type\":\"Grid\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"2708\"},{\"id\":\"2727\"},{\"id\":\"2728\"},{\"id\":\"2729\"},{\"id\":\"2730\"},{\"id\":\"2731\"}]},\"id\":\"2733\",\"type\":\"Toolbar\"},{\"attributes\":{\"data_source\":{\"id\":\"2746\"},\"glyph\":{\"id\":\"2749\"},\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2751\"},\"nonselection_glyph\":{\"id\":\"2750\"},\"selection_glyph\":null,\"view\":{\"id\":\"2753\"}},\"id\":\"2752\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data\":{\"beak depth (mm)\":{\"__ndarray__\":\"zczMzMzMIkAAAAAAAAAjQAAAAAAAACZAZmZmZmZmIUDNzMzMzMwgQDMzMzMzMyJAZmZmZmZmIUBmZmZmZmYkQDMzMzMzMyNAMzMzMzOzIUCamZmZmZkhQAAAAAAAACNAZmZmZmZmIkAAAAAAAAAiQJqZmZmZmSNAmpmZmZmZIkAAAAAAAAAiQGZmZmZmZiRAzczMzMzMHkAAAAAAAAAiQAAAAAAAACNAzczMzMzMIkAAAAAAAAAgQM3MzMzMzCFAzczMzMzMIkAAAAAAAAAjQAAAAAAAACBAAAAAAAAAJEBmZmZmZuYhQGZmZmZmZiBAmpmZmZmZIUBmZmZmZmYiQM3MzMzMzCJAAAAAAAAAI0AzMzMzMzMgQAAAAAAAACNAzczMzMzMIECamZmZmZkiQJqZmZmZmSJAMzMzMzMzI0BmZmZmZmYiQAAAAAAAACRAzczMzMzMIUAAAAAAAAAlQM3MzMzMzCFAMzMzMzMzIUCamZmZmZkhQM3MzMzMTCJAAAAAAAAAI0AzMzMzMzMiQGZmZmZmZiRAzczMzMzMIEAAAAAAAAAkQGZmZmZmZiRAmpmZmZmZIkCamZmZmZklQJqZmZmZmSBAMzMzMzMzH0CamZmZmZkjQJqZmZmZmR9AzczMzMzMIUDNzMzMzMweQM3MzMzMzCFAzczMzMzMIkDNzMzMzMwiQAAAAAAAACFAAAAAAAAAIUAzMzMzMzMjQGZmZmZmZiRAmpmZmZmZIUAAAAAAAAAjQJqZmZmZmSJAAAAAAAAAIkBmZmZmZmYiQGZmZmZmZiFAAAAAAAAAIkAzMzMzMzMiQGZmZmZmZiFAzczMzMzMIkCamZmZmZkjQDMzMzMzMyFAMzMzMzMzJUAAAAAAAAAiQAAAAAAAACNAMzMzMzMzIECamZmZmZkiQDMzMzMzMyNAAAAAAAAAIUBmZmZmZmYgQAAAAAAAACBAAAAAAAAAI0BmZmZmZmYjQM3MzMzMzCNAMzMzMzMzIkAAAAAAAAAjQJqZmZmZmSNAzczMzMzMIECamZmZmZkgQDMzMzMzMyNAzczMzMzMIkAAAAAAAAAkQM3MzMzMzCFAMzMzMzMzIkCamZmZmZkjQJqZmZmZmSJAzczMzMzMI0DNzMzMzMwhQAAAAAAAACFAMzMzMzMzJUCamZmZmZkiQM3MzMzMzCFAzczMzMzMIUBmZmZmZmYjQJqZmZmZmSNAAAAAAAAAJUDNzMzMzMwgQAAAAAAAACRAAAAAAAAAIkBmZmZmZmYhQJqZmZmZmSFAzczMzMzMIECamZmZmZkiQJqZmZmZmSNAzczMzMzMIUCamZmZmZkjQDMzMzMzMyJA\",\"dtype\":\"float64\",\"shape\":[126]},\"beak length (mm)\":{\"__ndarray__\":\"mpmZmZmZLEBmZmZmZmYrQJqZmZmZmStAAAAAAAAAKEAAAAAAAAAqQAAAAAAAACpAMzMzMzMzK0CamZmZmZkpQDMzMzMzMytAZmZmZmbmKUAzMzMzMzMqQM3MzMzMzCpAzczMzMzMK0CamZmZmZkoQAAAAAAAACxAAAAAAAAAKUCamZmZmZkoQM3MzMzMzCtAMzMzMzMzKkAAAAAAAAApQM3MzMzMzCtAZmZmZmZmK0AAAAAAAAAoQM3MzMzMzCxAAAAAAAAAK0CamZmZmZkrQAAAAAAAACpAzczMzMzMLUAAAAAAAAApQJqZmZmZmShAmpmZmZmZKUDNzMzMzMwqQJqZmZmZmStAAAAAAAAAK0AAAAAAAAArQM3MzMzMzCpAmpmZmZmZKEAzMzMzM7MsQGZmZmZmZipAmpmZmZmZK0AzMzMzMzMtQJqZmZmZmSxAmpmZmZmZK0AzMzMzMzMrQM3MzMzMzClAAAAAAAAAKkAAAAAAAAArQGZmZmZmZipAZmZmZmZmK0AzMzMzMzMqQGZmZmZmZipAMzMzMzMzKUAAAAAAAAAqQM3MzMzMzCtAZmZmZmZmKkAAAAAAAAAuQD0K16NwvSpAzczMzMzMJkCamZmZmZkrQAAAAAAAACpAAAAAAAAAKkAzMzMzMzMqQJqZmZmZmSlAmpmZmZmZKkAAAAAAAAArQM3MzMzMzChAMzMzMzMzKkAAAAAAAAAsQAAAAAAAACtAmpmZmZmZJ0BmZmZmZmYrQGZmZmZmZipAZmZmZmZmKEAAAAAAAAAqQDMzMzMzMypAZmZmZmZmLUBmZmZmZmYrQAAAAAAAACtAmpmZmZmZKkAzMzMzMzMsQAAAAAAAAClAZmZmZmZmK0AzMzMzMzMtQDMzMzMzMyxAzczMzMzMKUDNzMzMzMwrQM3MzMzMzCpAAAAAAAAAKkBmZmZmZmYpQDMzMzMzMyhAAAAAAAAALEDNzMzMzMwtQM3MzMzMzCtAzczMzMzMKUAzMzMzMzMtQAAAAAAAACxAAAAAAAAAKkBmZmZmZmYpQAAAAAAAACxAMzMzMzMzLEAzMzMzMzMsQAAAAAAAACpAAAAAAAAAK0DNzMzMzMwqQM3MzMzMzCtAMzMzMzMzKkDNzMzMzMwpQAAAAAAAACxAAAAAAAAALEAzMzMzMzMsQGZmZmZmZi1AzczMzMzMKkCamZmZmZkrQM3MzMzMzCpAmpmZmZmZK0DNzMzMzMwoQDMzMzMzMyxAzczMzMzMKUDNzMzMzMwrQJqZmZmZmSxAZmZmZmZmKkBmZmZmZmYsQAAAAAAAACpAMzMzMzMzLUAzMzMzMzMqQGZmZmZmZi5A\",\"dtype\":\"float64\",\"shape\":[126]},\"beak_depth_left_parenthesis_mm_right_parenthesis\":{\"__ndarray__\":\"zczMzMzMIkAAAAAAAAAjQAAAAAAAACZAZmZmZmZmIUDNzMzMzMwgQDMzMzMzMyJAZmZmZmZmIUBmZmZmZmYkQDMzMzMzMyNAMzMzMzOzIUCamZmZmZkhQAAAAAAAACNAZmZmZmZmIkAAAAAAAAAiQJqZmZmZmSNAmpmZmZmZIkAAAAAAAAAiQGZmZmZmZiRAzczMzMzMHkAAAAAAAAAiQAAAAAAAACNAzczMzMzMIkAAAAAAAAAgQM3MzMzMzCFAzczMzMzMIkAAAAAAAAAjQAAAAAAAACBAAAAAAAAAJEBmZmZmZuYhQGZmZmZmZiBAmpmZmZmZIUBmZmZmZmYiQM3MzMzMzCJAAAAAAAAAI0AzMzMzMzMgQAAAAAAAACNAzczMzMzMIECamZmZmZkiQJqZmZmZmSJAMzMzMzMzI0BmZmZmZmYiQAAAAAAAACRAzczMzMzMIUAAAAAAAAAlQM3MzMzMzCFAMzMzMzMzIUCamZmZmZkhQM3MzMzMTCJAAAAAAAAAI0AzMzMzMzMiQGZmZmZmZiRAzczMzMzMIEAAAAAAAAAkQGZmZmZmZiRAmpmZmZmZIkCamZmZmZklQJqZmZmZmSBAMzMzMzMzH0CamZmZmZkjQJqZmZmZmR9AzczMzMzMIUDNzMzMzMweQM3MzMzMzCFAzczMzMzMIkDNzMzMzMwiQAAAAAAAACFAAAAAAAAAIUAzMzMzMzMjQGZmZmZmZiRAmpmZmZmZIUAAAAAAAAAjQJqZmZmZmSJAAAAAAAAAIkBmZmZmZmYiQGZmZmZmZiFAAAAAAAAAIkAzMzMzMzMiQGZmZmZmZiFAzczMzMzMIkCamZmZmZkjQDMzMzMzMyFAMzMzMzMzJUAAAAAAAAAiQAAAAAAAACNAMzMzMzMzIECamZmZmZkiQDMzMzMzMyNAAAAAAAAAIUBmZmZmZmYgQAAAAAAAACBAAAAAAAAAI0BmZmZmZmYjQM3MzMzMzCNAMzMzMzMzIkAAAAAAAAAjQJqZmZmZmSNAzczMzMzMIECamZmZmZkgQDMzMzMzMyNAzczMzMzMIkAAAAAAAAAkQM3MzMzMzCFAMzMzMzMzIkCamZmZmZkjQJqZmZmZmSJAzczMzMzMI0DNzMzMzMwhQAAAAAAAACFAMzMzMzMzJUCamZmZmZkiQM3MzMzMzCFAzczMzMzMIUBmZmZmZmYjQJqZmZmZmSNAAAAAAAAAJUDNzMzMzMwgQAAAAAAAACRAAAAAAAAAIkBmZmZmZmYhQJqZmZmZmSFAzczMzMzMIECamZmZmZkiQJqZmZmZmSNAzczMzMzMIUCamZmZmZkjQDMzMzMzMyJA\",\"dtype\":\"float64\",\"shape\":[126]},\"beak_length_left_parenthesis_mm_right_parenthesis\":{\"__ndarray__\":\"mpmZmZmZLEBmZmZmZmYrQJqZmZmZmStAAAAAAAAAKEAAAAAAAAAqQAAAAAAAACpAMzMzMzMzK0CamZmZmZkpQDMzMzMzMytAZmZmZmbmKUAzMzMzMzMqQM3MzMzMzCpAzczMzMzMK0CamZmZmZkoQAAAAAAAACxAAAAAAAAAKUCamZmZmZkoQM3MzMzMzCtAMzMzMzMzKkAAAAAAAAApQM3MzMzMzCtAZmZmZmZmK0AAAAAAAAAoQM3MzMzMzCxAAAAAAAAAK0CamZmZmZkrQAAAAAAAACpAzczMzMzMLUAAAAAAAAApQJqZmZmZmShAmpmZmZmZKUDNzMzMzMwqQJqZmZmZmStAAAAAAAAAK0AAAAAAAAArQM3MzMzMzCpAmpmZmZmZKEAzMzMzM7MsQGZmZmZmZipAmpmZmZmZK0AzMzMzMzMtQJqZmZmZmSxAmpmZmZmZK0AzMzMzMzMrQM3MzMzMzClAAAAAAAAAKkAAAAAAAAArQGZmZmZmZipAZmZmZmZmK0AzMzMzMzMqQGZmZmZmZipAMzMzMzMzKUAAAAAAAAAqQM3MzMzMzCtAZmZmZmZmKkAAAAAAAAAuQD0K16NwvSpAzczMzMzMJkCamZmZmZkrQAAAAAAAACpAAAAAAAAAKkAzMzMzMzMqQJqZmZmZmSlAmpmZmZmZKkAAAAAAAAArQM3MzMzMzChAMzMzMzMzKkAAAAAAAAAsQAAAAAAAACtAmpmZmZmZJ0BmZmZmZmYrQGZmZmZmZipAZmZmZmZmKEAAAAAAAAAqQDMzMzMzMypAZmZmZmZmLUBmZmZmZmYrQAAAAAAAACtAmpmZmZmZKkAzMzMzMzMsQAAAAAAAAClAZmZmZmZmK0AzMzMzMzMtQDMzMzMzMyxAzczMzMzMKUDNzMzMzMwrQM3MzMzMzCpAAAAAAAAAKkBmZmZmZmYpQDMzMzMzMyhAAAAAAAAALEDNzMzMzMwtQM3MzMzMzCtAzczMzMzMKUAzMzMzMzMtQAAAAAAAACxAAAAAAAAAKkBmZmZmZmYpQAAAAAAAACxAMzMzMzMzLEAzMzMzMzMsQAAAAAAAACpAAAAAAAAAK0DNzMzMzMwqQM3MzMzMzCtAMzMzMzMzKkDNzMzMzMwpQAAAAAAAACxAAAAAAAAALEAzMzMzMzMsQGZmZmZmZi1AzczMzMzMKkCamZmZmZkrQM3MzMzMzCpAmpmZmZmZK0DNzMzMzMwoQDMzMzMzMyxAzczMzMzMKUDNzMzMzMwrQJqZmZmZmSxAZmZmZmZmKkBmZmZmZmYsQAAAAAAAACpAMzMzMzMzLUAzMzMzMzMqQGZmZmZmZi5A\",\"dtype\":\"float64\",\"shape\":[126]},\"species\":[\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\",\"scandens\"],\"year\":[2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012]},\"selected\":{\"id\":\"2755\"},\"selection_policy\":{\"id\":\"2770\"}},\"id\":\"2754\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2752\"},{\"id\":\"2760\"}],\"tags\":[\"hv_created\"],\"tooltips\":[[\"species\",\"@{species}\"],[\"beak length (mm)\",\"@{beak_length_left_parenthesis_mm_right_parenthesis}\"],[\"beak depth (mm)\",\"@{beak_depth_left_parenthesis_mm_right_parenthesis}\"],[\"year\",\"@{year}\"]]},\"id\":\"2708\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2728\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"2742\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"2755\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"beak depth (mm)\",\"bounds\":\"auto\",\"formatter\":{\"id\":\"2742\"},\"major_label_orientation\":\"horizontal\",\"ticker\":{\"id\":\"2724\"}},\"id\":\"2723\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2720\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis_label\":\"beak length (mm)\",\"bounds\":\"auto\",\"formatter\":{\"id\":\"2740\"},\"major_label_orientation\":\"horizontal\",\"ticker\":{\"id\":\"2720\"}},\"id\":\"2719\",\"type\":\"LinearAxis\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#ff7e0e\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#ff7e0e\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2759\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2770\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end\":12.989999999999998,\"reset_end\":12.989999999999998,\"reset_start\":6.61,\"start\":6.61,\"tags\":[[[\"beak depth (mm)\",\"beak depth (mm)\",null]]]},\"id\":\"2707\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"2724\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"2729\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"2768\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"2715\",\"type\":\"LinearScale\"},{\"attributes\":{\"axis\":{\"id\":\"2719\"},\"ticker\":{\"id\":\"2720\"}},\"id\":\"2722\",\"type\":\"Grid\"},{\"attributes\":{\"end\":16.28388888888889,\"reset_end\":16.28388888888889,\"reset_start\":8.41611111111111,\"start\":8.41611111111111,\"tags\":[[[\"beak length (mm)\",\"beak length (mm)\",null]]]},\"id\":\"2706\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"2717\",\"type\":\"LinearScale\"},{\"attributes\":{\"data\":{\"beak depth (mm)\":{\"__ndarray__\":\"AAAAAAAAIUDNzMzMzMwhQAAAAAAAAB5AMzMzMzMzI0BmZmZmZmYiQGZmZmZmZiBAMzMzMzMzH0AzMzMzMzMhQM3MzMzMzCBAzczMzMzMHkAAAAAAAAAgQGZmZmZmZiFAMzMzMzMzIECamZmZmZkhQM3MzMzMzCJAAAAAAAAAJEAzMzMzMzMjQDMzMzMzMyNAMzMzMzMzIEAAAAAAAAAeQM3MzMzMzCBAmpmZmZmZH0CamZmZmZkgQM3MzMzMzCFAMzMzMzMzIkDNzMzMzMweQJqZmZmZmSBAMzMzMzMzIUDNzMzMzMwgQM3MzMzMzB5AMzMzMzMzIkDNzMzMzMweQAAAAAAAACJAZmZmZmZmJEAzMzMzMzMgQDMzMzMzMyFAzczMzMzMIEAzMzMzMzMgQAAAAAAAACBAmpmZmZmZIECamZmZmZkkQAAAAAAAACBAmpmZmZmZIUAAAAAAAAAiQJqZmZmZmSJAZmZmZmZmHkBmZmZmZmYgQAAAAAAAACRAZmZmZmZmIEBmZmZmZmYgQJqZmZmZmSBAMzMzMzMzH0AAAAAAAAAgQM3MzMzMzCBAmpmZmZmZIkDNzMzMzMwhQGZmZmZmZiNAZmZmZmZmHkAAAAAAAAAiQDMzMzMzMyFAzczMzMzMIUAzMzMzMzMhQJqZmZmZmSFAAAAAAAAAIUBmZmZmZmYiQAAAAAAAACBAzczMzMzMIkDNzMzMzMweQM3MzMzMzCBAAAAAAAAAIUAAAAAAAAAiQAAAAAAAACJAmpmZmZmZIkBmZmZmZmYhQDMzMzMzMyBAZmZmZmZmIUCamZmZmZkfQM3MzMzMzB5AzczMzMzMIEAAAAAAAIAiQDMzMzMzMyBAmpmZmZmZIEAAAAAAAAAhQM3MzMzMzCNAzczMzMzMIEDNzMzMzMwjQM3MzMzMzBxAZmZmZmZmIEBmZmZmZmYgQJqZmZmZmSBAzczMzMzMIEAAAAAAAAAeQGZmZmZmZiBAMzMzMzMzIUBmZmZmZmYgQJqZmZmZmSFAAAAAAAAAIUAzMzMzMzMgQJqZmZmZmSBAAAAAAAAAIUAzMzMzMzMgQDMzMzMzMx1AAAAAAAAAIEBmZmZmZmYkQDMzMzMzMyZAzczMzMzMI0BmZmZmZmYhQJqZmZmZmSBAMzMzMzMzH0DNzMzMzMwjQJqZmZmZmSRAzczMzMzMIEBmZmZmZmYhQJqZmZmZmSNAZmZmZmZmIUAAAAAAAAAiQDMzMzMzMx9AAAAAAAAAIUBmZmZmZmYgQGZmZmZmZiJAAAAAAAAAIkA=\",\"dtype\":\"float64\",\"shape\":[121]},\"beak length (mm)\":{\"__ndarray__\":\"AAAAAAAAJEAAAAAAAAApQJqZmZmZmSJAmpmZmZmZJEAAAAAAAAAmQDMzMzMzMyRAMzMzMzMzI0DNzMzMzMwlQJqZmZmZmSRAmpmZmZmZI0AzMzMzMzMkQM3MzMzMzCRAMzMzMzMzI0AzMzMzMzMlQDMzMzMzMyVAzczMzMzMJ0CamZmZmZkmQJqZmZmZmSZAZmZmZmZmI0BmZmZmZmYjQDMzMzMzMyRAAAAAAAAAJEAAAAAAAAAkQAAAAAAAACRAAAAAAAAAJ0AAAAAAAAAjQGZmZmZmZiZAZmZmZmZmJUAAAAAAAAAkQJqZmZmZmSNAzczMzMzMJUBmZmZmZmYiQGZmZmZmZiRAmpmZmZmZJkCamZmZmZkkQGZmZmZmZiVAAAAAAAAAJEBmZmZmZmYjQM3MzMzMzCNAZmZmZmZmJUAAAAAAAAAmQGZmZmZmZiNAAAAAAAAAJUBmZmZmZmYnQJqZmZmZmSVAMzMzMzMzIkDNzMzMzMwlQGZmZmZmZihAzczMzMzMJUBmZmZmZmYlQM3MzMzMzCRAZmZmZmZmI0CamZmZmZkkQJqZmZmZmSNAMzMzMzMzJUAAAAAAAAAlQAAAAAAAAClAZmZmZmZmIkAzMzMzMzMkQDMzMzMzMyVAAAAAAAAAJ0CamZmZmZklQAAAAAAAACVAMzMzMzMzJEBmZmZmZmYlQDMzMzMzMyNAZmZmZmZmJUAzMzMzMzMkQAAAAAAAACRAAAAAAAAAJEDNzMzMzMwkQM3MzMzMzCRAZmZmZmZmJ0AzMzMzMzMlQAAAAAAAACdAZmZmZmZmJUDNzMzMzMwkQDMzMzMzMyRAmpmZmZmZJUAAAAAAAAAnQDMzMzMzMyZAzczMzMzMI0AAAAAAAAAlQGZmZmZmZihAzczMzMzMJUDNzMzMzMwpQGZmZmZmZiNAZmZmZmZmI0AAAAAAAAAkQDMzMzMzMyRAZmZmZmZmJEAzMzMzMzMjQM3MzMzMzCNAMzMzMzMzJUCamZmZmZkjQDMzMzMzMyZAAAAAAAAAJEDNzMzMzMwlQAAAAAAAACRAMzMzMzMzJUBmZmZmZmYlQM3MzMzMzCJAMzMzMzMzJECamZmZmZknQGZmZmZmZihAzczMzMzMKUAzMzMzMzMkQDMzMzMzMyRAAAAAAAAAIkBmZmZmZmYnQM3MzMzMzCVAzczMzMzMJEBmZmZmZmYpQAAAAAAAACVAMzMzMzMzI0AzMzMzMzMlQM3MzMzMzCRAAAAAAAAAJUAzMzMzMzMkQDMzMzMzMyVAMzMzMzMzJUA=\",\"dtype\":\"float64\",\"shape\":[121]},\"beak_depth_left_parenthesis_mm_right_parenthesis\":{\"__ndarray__\":\"AAAAAAAAIUDNzMzMzMwhQAAAAAAAAB5AMzMzMzMzI0BmZmZmZmYiQGZmZmZmZiBAMzMzMzMzH0AzMzMzMzMhQM3MzMzMzCBAzczMzMzMHkAAAAAAAAAgQGZmZmZmZiFAMzMzMzMzIECamZmZmZkhQM3MzMzMzCJAAAAAAAAAJEAzMzMzMzMjQDMzMzMzMyNAMzMzMzMzIEAAAAAAAAAeQM3MzMzMzCBAmpmZmZmZH0CamZmZmZkgQM3MzMzMzCFAMzMzMzMzIkDNzMzMzMweQJqZmZmZmSBAMzMzMzMzIUDNzMzMzMwgQM3MzMzMzB5AMzMzMzMzIkDNzMzMzMweQAAAAAAAACJAZmZmZmZmJEAzMzMzMzMgQDMzMzMzMyFAzczMzMzMIEAzMzMzMzMgQAAAAAAAACBAmpmZmZmZIECamZmZmZkkQAAAAAAAACBAmpmZmZmZIUAAAAAAAAAiQJqZmZmZmSJAZmZmZmZmHkBmZmZmZmYgQAAAAAAAACRAZmZmZmZmIEBmZmZmZmYgQJqZmZmZmSBAMzMzMzMzH0AAAAAAAAAgQM3MzMzMzCBAmpmZmZmZIkDNzMzMzMwhQGZmZmZmZiNAZmZmZmZmHkAAAAAAAAAiQDMzMzMzMyFAzczMzMzMIUAzMzMzMzMhQJqZmZmZmSFAAAAAAAAAIUBmZmZmZmYiQAAAAAAAACBAzczMzMzMIkDNzMzMzMweQM3MzMzMzCBAAAAAAAAAIUAAAAAAAAAiQAAAAAAAACJAmpmZmZmZIkBmZmZmZmYhQDMzMzMzMyBAZmZmZmZmIUCamZmZmZkfQM3MzMzMzB5AzczMzMzMIEAAAAAAAIAiQDMzMzMzMyBAmpmZmZmZIEAAAAAAAAAhQM3MzMzMzCNAzczMzMzMIEDNzMzMzMwjQM3MzMzMzBxAZmZmZmZmIEBmZmZmZmYgQJqZmZmZmSBAzczMzMzMIEAAAAAAAAAeQGZmZmZmZiBAMzMzMzMzIUBmZmZmZmYgQJqZmZmZmSFAAAAAAAAAIUAzMzMzMzMgQJqZmZmZmSBAAAAAAAAAIUAzMzMzMzMgQDMzMzMzMx1AAAAAAAAAIEBmZmZmZmYkQDMzMzMzMyZAzczMzMzMI0BmZmZmZmYhQJqZmZmZmSBAMzMzMzMzH0DNzMzMzMwjQJqZmZmZmSRAzczMzMzMIEBmZmZmZmYhQJqZmZmZmSNAZmZmZmZmIUAAAAAAAAAiQDMzMzMzMx9AAAAAAAAAIUBmZmZmZmYgQGZmZmZmZiJAAAAAAAAAIkA=\",\"dtype\":\"float64\",\"shape\":[121]},\"beak_length_left_parenthesis_mm_right_parenthesis\":{\"__ndarray__\":\"AAAAAAAAJEAAAAAAAAApQJqZmZmZmSJAmpmZmZmZJEAAAAAAAAAmQDMzMzMzMyRAMzMzMzMzI0DNzMzMzMwlQJqZmZmZmSRAmpmZmZmZI0AzMzMzMzMkQM3MzMzMzCRAMzMzMzMzI0AzMzMzMzMlQDMzMzMzMyVAzczMzMzMJ0CamZmZmZkmQJqZmZmZmSZAZmZmZmZmI0BmZmZmZmYjQDMzMzMzMyRAAAAAAAAAJEAAAAAAAAAkQAAAAAAAACRAAAAAAAAAJ0AAAAAAAAAjQGZmZmZmZiZAZmZmZmZmJUAAAAAAAAAkQJqZmZmZmSNAzczMzMzMJUBmZmZmZmYiQGZmZmZmZiRAmpmZmZmZJkCamZmZmZkkQGZmZmZmZiVAAAAAAAAAJEBmZmZmZmYjQM3MzMzMzCNAZmZmZmZmJUAAAAAAAAAmQGZmZmZmZiNAAAAAAAAAJUBmZmZmZmYnQJqZmZmZmSVAMzMzMzMzIkDNzMzMzMwlQGZmZmZmZihAzczMzMzMJUBmZmZmZmYlQM3MzMzMzCRAZmZmZmZmI0CamZmZmZkkQJqZmZmZmSNAMzMzMzMzJUAAAAAAAAAlQAAAAAAAAClAZmZmZmZmIkAzMzMzMzMkQDMzMzMzMyVAAAAAAAAAJ0CamZmZmZklQAAAAAAAACVAMzMzMzMzJEBmZmZmZmYlQDMzMzMzMyNAZmZmZmZmJUAzMzMzMzMkQAAAAAAAACRAAAAAAAAAJEDNzMzMzMwkQM3MzMzMzCRAZmZmZmZmJ0AzMzMzMzMlQAAAAAAAACdAZmZmZmZmJUDNzMzMzMwkQDMzMzMzMyRAmpmZmZmZJUAAAAAAAAAnQDMzMzMzMyZAzczMzMzMI0AAAAAAAAAlQGZmZmZmZihAzczMzMzMJUDNzMzMzMwpQGZmZmZmZiNAZmZmZmZmI0AAAAAAAAAkQDMzMzMzMyRAZmZmZmZmJEAzMzMzMzMjQM3MzMzMzCNAMzMzMzMzJUCamZmZmZkjQDMzMzMzMyZAAAAAAAAAJEDNzMzMzMwlQAAAAAAAACRAMzMzMzMzJUBmZmZmZmYlQM3MzMzMzCJAMzMzMzMzJECamZmZmZknQGZmZmZmZihAzczMzMzMKUAzMzMzMzMkQDMzMzMzMyRAAAAAAAAAIkBmZmZmZmYnQM3MzMzMzCVAzczMzMzMJEBmZmZmZmYpQAAAAAAAACVAMzMzMzMzI0AzMzMzMzMlQM3MzMzMzCRAAAAAAAAAJUAzMzMzMzMkQDMzMzMzMyVAMzMzMzMzJUA=\",\"dtype\":\"float64\",\"shape\":[121]},\"species\":[\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\",\"fortis\"],\"year\":[2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012,2012]},\"selected\":{\"id\":\"2747\"},\"selection_policy\":{\"id\":\"2768\"}},\"id\":\"2746\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"2727\",\"type\":\"SaveTool\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.75},\"fill_color\":{\"value\":\"#1f77b3\"},\"line_alpha\":{\"value\":0.75},\"line_color\":{\"value\":\"#1f77b3\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2749\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.75},\"fill_color\":{\"value\":\"#ff7e0e\"},\"line_alpha\":{\"value\":0.75},\"line_color\":{\"value\":\"#ff7e0e\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2757\",\"type\":\"Scatter\"},{\"attributes\":{\"text\":\"year: 1973\"},\"id\":\"2711\",\"type\":\"Title\"},{\"attributes\":{\"overlay\":{\"id\":\"2732\"}},\"id\":\"2730\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"2747\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.75},\"fill_color\":{\"value\":\"#1f77b3\"},\"line_alpha\":{\"value\":0.75},\"line_color\":{\"value\":\"#1f77b3\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2750\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#1f77b3\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#1f77b3\"},\"x\":{\"field\":\"beak length (mm)\"},\"y\":{\"field\":\"beak depth (mm)\"}},\"id\":\"2751\",\"type\":\"Scatter\"}],\"root_ids\":[\"2710\"]},\"title\":\"Bokeh Application\",\"version\":\"2.0.2\"}};\n",
" var render_items = [{\"docid\":\"1b8cb8a9-ecdb-4a8e-8c6c-17e7d67e521e\",\"root_ids\":[\"2710\"],\"roots\":{\"2710\":\"a3735683-ccd6-4df4-b706-7f3aa07200b2\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
"\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" var attempts = 0;\n",
" var timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "2710"
}
},
"output_type": "display_data"
}
],
"source": [
"hv_fig = hv.Points(\n",
" data=df,\n",
" kdims=['beak length (mm)', 'beak depth (mm)'],\n",
" vdims=['species', 'year'],\n",
").groupby(\n",
" ['species', 'year'],\n",
").opts(\n",
" tools=['hover'],\n",
" show_legend=False,\n",
").overlay(\n",
" 'species',\n",
")\n",
"\n",
"# Take out the Bokeh object\n",
"p = hv.render(hv_fig)\n",
"\n",
"# Display using Bokeh\n",
"bokeh.io.show(p)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we got the plot for 1973, which was the first year offered by the interactive HoloMap. If we wanted another year, we would have to make a plot specifically for that year."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Other kinds of plots\n",
"\n",
"We have seen the basics of how HoloViews works for a scatter plot specified by `hv.Points`. We now show some other kinds of plots we have encountered until now."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Smooth function\n",
"\n",
"HoloViews can plot a smooth function using the `hv.Curve`. For a Curve, there is one key dimension, which is the independent variable, and one value dimension, which is the dependent variable. This is to be contrasted with `hv.Path`, which has two key dimensions, meaning that neither of the variables is strictly dependent on the other.\n",
"\n",
"Here is a HoloViews plot of the x-section of the Airy disk. We can either provide a data frame with columns, or we can provide a 2-tuple of NumPy arrays that serve as the dependent and independent variable, respectively."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Curve [x] (normalized intensity)"
]
},
"execution_count": 12,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "2908"
}
},
"output_type": "execute_result"
}
],
"source": [
"# The x-values we want\n",
"x = np.linspace(-15, 15, 400)\n",
"\n",
"# The normalized intensity\n",
"norm_I = 4 * (scipy.special.j1(x) / x)**2\n",
"\n",
"hv.Curve(\n",
" data=(x, norm_I),\n",
" kdims='x',\n",
" vdims='normalized intensity'\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Box plot\n",
"\n",
"Box plots are made using `hv.BoxWhisker` elements. If multiple key dimensions are specified, nested categorical axes are automatically set up."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":BoxWhisker [species,year] (beak depth (mm))"
]
},
"execution_count": 13,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "3005"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.BoxWhisker(\n",
" data=df,\n",
" kdims=['species', 'year'],\n",
" vdims=['beak depth (mm)'],\n",
").opts(\n",
" box_color='species',\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Strip plots\n",
"\n",
"We use `hv.Scatter()` to generate strip plots. When we specify the `jitter` kwargs, we specify the width of the jitter.\n",
"\n",
"Note that nested categorical axes are currently (as of June 14, 2020) only supported for box, violin, and bar plots, as [per the docs](http://holoviews.org/user_guide/Customizing_Plots.html#Categorical-axes) but will eventually be supported for many more plot types, including `Scatter`, which are used to generate strip plots."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":NdLayout [species]\n",
" :Scatter [year_str] (beak depth (mm),species)"
]
},
"execution_count": 14,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "3214"
}
},
"output_type": "execute_result"
}
],
"source": [
"# Make the year column a string to can use as categorical\n",
"df['year_str'] = df['year'].astype(str)\n",
"\n",
"hv.Scatter(\n",
" data=df,\n",
" kdims=[('year_str', 'year')],\n",
" vdims=['beak depth (mm)', 'species'],\n",
").groupby(\n",
" 'species'\n",
").opts(\n",
" color='species',\n",
" jitter=0.4,\n",
" show_legend=False,\n",
" width=400,\n",
" height=250,\n",
").layout(\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Histograms\n",
"\n",
"When making a histogram, the values of the bin edges and counts must be computed beforehand using `np.histogram()`."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"edges, counts = np.histogram(df_2012['beak depth (mm)'], bins=int(np.sqrt(len(df_2012))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We then can pass the bin edges and counts into `hv.Histogram()`."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Histogram [beak depth (mm)] (Frequency)"
]
},
"execution_count": 16,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "3543"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Histogram(\n",
" data=(edges, counts),\n",
" kdims='beak depth (mm)'\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ECDFs\n",
"\n",
"HoloViews does not have native support for ECDFs ([my fault](https://github.com/holoviz/holoviews/issues/3821); I'm the one who is supposed to add this), but we can create ECDFs in a data frame and use `hv.Scatter` to make a plot of an ECDF."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def ecdf_transform(data):\n",
" return data.rank(method=\"first\") / len(data)\n",
"\n",
"df_2012[\"beak depth ECDF\"] = df_2012.groupby(\"species\")[\n",
" \"beak depth (mm)\"\n",
"].transform(ecdf_transform).values"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After supplying the y-values for the ECDF, we plot with `hv.Scatter`."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"
\n",
"
\n",
""
],
"text/plain": [
":NdOverlay [species]\n",
" :Scatter [beak depth (mm)] (beak depth ECDF,species)"
]
},
"execution_count": 18,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": "3640"
}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Scatter(\n",
" data=df_2012,\n",
" kdims='beak depth (mm)',\n",
" vdims=[('beak depth ECDF', 'ECDF'), 'species'],\n",
").groupby(\n",
" 'species'\n",
").overlay(\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusions\n",
"\n",
"HoloViews is one of many high-level plotting libraries in Python. Others include [Altair](https://altair-viz.github.io), [Seaborn](https://seaborn.pydata.org), and [ggplot](http://ggplot.yhathq.com). There is a pretty complete list available from [PyViz](https://pyviz.org/tools.html). HoloViews is my personal favorite, though, because of easy rendering with Bokeh and clear logic connecting annotated data sets to graphics.\n",
"\n",
"We have only begun to scratch the surface of what HoloViews can do. You can explore [HoloView's extensive documentation](http://holoviews.org/index.html) to check out more of its capabilities. \n",
"\n",
"In the next few lessons, we will explore dealing with overplotting and dashboarding, two powerful plotting techniques you may not have thought about that can be transformative for your research."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Computing environment"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPython 3.7.7\n",
"IPython 7.13.0\n",
"\n",
"numpy 1.18.1\n",
"scipy 1.4.1\n",
"pandas 0.24.2\n",
"bootcamp_utils 0.0.6\n",
"bokeh 2.0.2\n",
"holoviews 1.13.2\n",
"datashader 0.10.0\n",
"jupyterlab 1.2.6\n"
]
}
],
"source": [
"%load_ext watermark\n",
"%watermark -v -p numpy,scipy,pandas,bootcamp_utils,bokeh,holoviews,datashader,jupyterlab"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}