#!/usr/bin/env python # coding: utf-8 # # # # # #
# # # # #

Bokeh Tutorial

#
# #

01. Basic Plotting

# This section of the tutorial covers the [`bokeh.plotting`](https://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html) # interface. This interface is a "mid-level" interface, and the main idea can be described by the statement: # # **Starting from simple default figures (with sensible default tools, grids and axes), add markers and other shapes whose visual attributes are tied to directly data.** # # We will see that it is possible to customize and change all of the defaults, but having them means that it is possible to get up and running very quickly. # # Imports and Setup # # When using the [`bokeh.plotting`](https://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html) interface, there are a few common imports: # * Use the [`figure`](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure) function to create new plot objects to work with. # * Call the functions [`output_file`](https://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.io.output_file) or [`output_notebook`](https://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.io.output_notebook) (possibly in combination) to tell Bokeh how to display or save output. # * Execute [`show`](https://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.io.show) and [`save`](https://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.io.save) to display or save plots and layouts. # In[ ]: import numpy as np # we will use this later, so import it now from bokeh.io import output_notebook, show from bokeh.plotting import figure # In this case, we are in the Jupyter notebook, so we will call `output_notebook()` below. We only need to call this once, and all subsequent calls to `show()` will display inline in the notebook. # In[ ]: output_notebook() # If everything is working, you should see a Bokeh logo and a message like *\"BokehJS 1.4.0 successfully loaded."* as the output. # This notebook uses Bokeh sample data. If you haven't downloaded it already, this can be downloaded by running the following: # In[ ]: import bokeh.sampledata bokeh.sampledata.download() # # Scatter Plots # # Bokeh can draw many types of visual shapes (called *glyphs*), including lines, bars, patches, hex tiles and more. One of the most common visualization tasks is to draw a scatter plot of data using small *marker* glyphs to represent each point. # # In this section you will see how to use Bokeh's various marker glyphs to create simple scatter plots. # # The basic outline is: # * create a blank figure: `p = figure(...)` # * call a glyph method such as `p.circle` on the figure # * `show` the figure # # Execute the cell below to create a small scatter plot with circle glyphs: # In[ ]: # create a new plot with default tools, using figure p = figure(width=400, height=400) # add a circle renderer with x and y coordinates, size, color, and alpha p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=15, line_color="navy", fill_color="orange", fill_alpha=0.5) show(p) # show the results # In the output above, you can see the effect of the different options for `line_color`, `fill_alpha`, etc. Try changing some of these values and re-executing the cell to update the plot. # All Bokeh scatter markers accept `size` (measured in screen space units) as a property. Circles in particular also have `radius` (measured in "data" space units). # In[ ]: # EXERCISE: Try changing the example above to set a `radius` value instead of `size` # To scatter square markers instead of circles, you can use the `square` method on figures. # In[ ]: # create a new plot using figure p = figure(width=400, height=400) # add a square renderer with a size, color, alpha, and sizes p.square([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=[10, 15, 20, 25, 30], color="firebrick", alpha=0.6) show(p) # show the results # Note that in the example above, we are also specifying different sizes for each individual marker. **In general, all of a glyph's properties can be "vectorized" in this fashion.** Also note that we have passed ``color`` as a shorthand to set both the line and fill colors easily at the same time. This is a convenience specific to ``bokeh.plotting``. # # There are many marker types available in Bokeh, you can see details and # example plots for all of them in the reference guide by clicking on entries in the list below: # # * [asterisk()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.asterisk) # * [circle()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.circle) # * [circle_cross()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.circle_cross) # * [circle_x()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.circle_x) # * [cross()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.cross) # * [diamond()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.diamond) # * [diamond_cross()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.diamond_cross) # * [hex()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.hex) # * [inverted_triangle()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.inverted_triangle) # * [square()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.square) # * [square_cross()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.square_cross) # * [square_x()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.square_x) # * [triangle()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.triangle) # * [x()](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.x) # In[ ]: # EXERCISE: Make a scatter plot using the "autompg" dataset from bokeh.sampledata.autompg import autompg as df # run df.head() to inspect # # Line Plots # # Another common visualization task is the drawing of line plots. This can be accomplished in Bokeh by calling the `p.line(...)` glyph method as shown below. # In[ ]: # create a new plot (with a title) using figure p = figure(width=400, height=400, title="My Line Plot") # add a line renderer p.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=2) show(p) # show the results # In addition to `line_width`, there are other options such as `line_color` or `line_dash` that can be set. Try setting some of the [other properties of line](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.line) and re-running the cell above. # ### Datetime axes # # It's often the case that timeseries data is represented by drawing lines. Let's look at an example using the "glucose" data set, which is available in a Pandas dataframe: # In[ ]: from bokeh.sampledata.glucose import data data.head() # We'd like to plot a subset of this data, and have a nice datetime axis as well. We can ask Bokeh for a datetime axis by passing `x_axis_type="datetime"` to the call to `figure`. This is shown below, as well as configuration of a some other options such as plot dimensions, axis titles, and grid line properies. # In[ ]: # reduce data size to one week week = data.loc['2010-10-01':'2010-10-08'] p = figure(x_axis_type="datetime", title="Glocose Range", height=350, width=800) p.xgrid.grid_line_color=None p.ygrid.grid_line_alpha=0.5 p.xaxis.axis_label = 'Time' p.yaxis.axis_label = 'Value' p.line(week.index, week.glucose) show(p) # In[ ]: # EXERCISE: Look at the AAPL data from bokeh.sampledata.stocks and create a line plot using it from bokeh.sampledata.stocks import AAPL # AAPL.keys() # dict_keys(['date', 'open', 'high', 'low', 'close', 'volume', 'adj_close']) dates = np.array(AAPL['date'], dtype=np.datetime64) # convert date strings to real datetimes # # Hex Tiling # # Bokeh supports drawing low level hex tilings using [axial coordinates](https://www.redblobgames.com/grids/hexagons/#coordinates-axial) and the `hex_tile` method, as described in the [Hex Tiles](https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#hex-tiles) section of the User's Guide. However, one of the most common uses of hex tilings is to visualize binning. Bokeh encapsulates this common operation in the `hexbin` function, whose output can be passed directly to `hex_tile` as seen below. # In[ ]: from bokeh.palettes import Viridis256 from bokeh.util.hex import hexbin n = 50000 x = np.random.standard_normal(n) y = np.random.standard_normal(n) bins = hexbin(x, y, 0.1) # color map the bins by hand, will see how to use linear_cmap later color = [Viridis256[int(i)] for i in bins.counts/max(bins.counts)*255] # match_aspect ensures neither dimension is squished, regardless of the plot size p = figure(tools="wheel_zoom,reset", match_aspect=True, background_fill_color='#440154') p.grid.visible = False p.hex_tile(bins.q, bins.r, size=0.1, line_color=None, fill_color=color) show(p) # In[ ]: # Exercise: Experiment with the size parameter to hexbin, and using different data as input # # Images # # Another common task is to display images, which might represent heat maps, or sensor data of some sort. Bokeh provides two glyph methods for displaying images: # # * `image` which can be used, together with a palette, to show colormapped 2d data in a plot # * `image_rgba` which can be used to display raw RGBA pixel data in a plot. # # The first example below shows how to call `image` with a 2d array and a palette # In[ ]: N = 500 x = np.linspace(0, 10, N) y = np.linspace(0, 10, N) xx, yy = np.meshgrid(x, y) img = np.sin(xx)*np.cos(yy) p = figure(x_range=(0, 10), y_range=(0, 10)) # must give a vector of image data for image parameter p.image(image=[img], x=0, y=0, dw=10, dh=10, palette="Spectral11") show(p) # A palette can be any list of colors, or one of the named built-in palettes, which can be seen in the [bokeh.palettes reference guide](https://bokeh.pydata.org/en/latest/docs/reference/palettes.html). Try changing the palette, or the array data and re-running the cell above. # # The next example shows how to use the `image_rgba` method to display raw RGBA data (created with help from NumPy). # In[ ]: from __future__ import division import numpy as np N = 20 img = np.empty((N,N), dtype=np.uint32) # use an array view to set each RGBA channel individiually view = img.view(dtype=np.uint8).reshape((N, N, 4)) for i in range(N): for j in range(N): view[i, j, 0] = int(i/N*255) # red view[i, j, 1] = 158 # green view[i, j, 2] = int(j/N*255) # blue view[i, j, 3] = 255 # alpha # create a new plot (with a fixed range) using figure p = figure(x_range=[0,10], y_range=[0,10]) # add an RGBA image renderer p.image_rgba(image=[img], x=[0], y=[0], dw=[10], dh=[10]) show(p) # Try changing the RGBA data and re-running the cell above. # # Other Kinds of Glyphs # # Bokeh supports many other kinds of glyphs. You can click on the User Guide links below to see how to create plots with these glyphs using the [`bokeh.plotting`](https://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html) interface. # # * [Ovals and Ellipses](https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#ovals-and-ellipses) # * [Segments and Rays](https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#segments-and-rays) # * [Wedges and Arcs](https://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html#wedges-and-arcs) # * [Specialized Curves](https://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html#specialized-curves) # # We will cover various kinds of Bar plots (e.g. with stacking and grouping) using [Bars and Rectangles](https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#bars-and-rectangles) much more extensively in the [Bar and Categorical Data Plots](07%20-%20Bar%20and%20Categorical%20Data%20Plots.ipynb) chapter of this tutorial. # In[ ]: # EXERCISE: Plot some of the other glyph types, following the examples in the User Guide. # # Plots with Multiple Glyphs # # Finally, it should be noted that is possible to combine more than one glyph on a single figure. When multiple calls to glyph methods happen on a single figure, the glyphs are draw in the order called, as shown below. # In[ ]: # set up some data x = [1, 2, 3, 4, 5] y = [6, 7, 8, 7, 3] # create a new plot with figure p = figure(width=400, height=400) # add both a line and circles on the same plot p.line(x, y, line_width=2) p.circle(x, y, fill_color="white", size=8) show(p) # show the results # In[ ]: # EXERCISE: create your own plot combining multiple glyphs together # # Next Section # Click on this link to go to the next notebook: [02 - Styling and Theming](02%20-%20Styling%20and%20Theming.ipynb). # # To go back to the overview, click [here](00%20-%20Introduction%20and%20Setup.ipynb). # In[ ]: