Section 01 focused on specifying elements and simple collections of them. This section explains how the visual appearance can be adjusted to bring out the most salient aspects of your data, or just to make the style match the overall theme of your document.
In the introduction to elements, hv.extension('bokeh')
was used at the start to load and activate the bokeh plotting extension. In this notebook, we will also briefly use matplotlib which we will load, but not yet activate, by listing it second:
In [ ]:
import pandas as pd
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
Let us find some interesting data to generate elements from, before we consider how to customize them. Here is a dataset containing information about all the eclipses of the 21st century:
In [ ]:
eclipses = pd.read_csv('../data/eclipses_21C.csv', parse_dates=['date'])
eclipses.head()
Here we have the date of each eclipse, what time of day the eclipse reached its peak in both local time and in UTC, the type of eclipse, its magnitude (fraction of the Sun's diameter obscured by the Moon) and the position of the peak in latitude and longitude.
Let's see what happens if we pass this dataframe to the Curve
element:
In [ ]:
hv.Curve(eclipses)
We see that, by default, the first dataframe column becomes the key dimension (corresponding to the x-axis) and the second column becomes the value dimension (corresponding to the y-axis). There is clearly structure in this data, but the plot is too highly compressed in the x direction to see much detail, and you may not like the particular color or line style. So we can start customizing the appearance of this curve using the HoloViews options system.
If we want to change the appearance of what we can already see in the plot, we're no longer focusing on the data and metadata stored in the elements, but about details of the presentation. Details specific to the final plo tare handled by the separate "options" system, not the element objects. HoloViews allows you to set three types of options:
We noted that the data is too compressed in the x direction. Let us fix that by specifying the width
plot option:
In [ ]:
%%opts Curve [width=900]
hour_curve = hv.Curve(eclipses).redim.label(hour_local='Hour (local time)', date='Date (21st century)')
hour_curve
The top line uses a special IPython/Jupyter syntax called the %%opts
cell magic to specify the width
plot option for all Curve
objects in this cell. %%opts
accepts a simple specification where we pass the width=900
keyword argument to Curve
as a plot option (denoted by the square brackets).
Of course, there are other ways of applying options in HoloViews that do not require this IPython-specific syntax, but for this tutorial, we will only be covering the more-convenient magic-based syntax. You can read about the alternative approaches in the user guide.
In [ ]:
# Exercise: Try setting the height plot option of the Curve above.
# Hint: the magic supports tab completion when the cursor is in the square brackets!
In [ ]:
# Exercise: Try enabling the boolean show_grid plot option for the curve above
In [ ]:
# Exercise: Try set the x-axis label rotation (in degrees) with the xrotation plot option
In [ ]:
# hv.help(hv.Curve)
In [ ]:
%%opts Curve (color='red' line_width=2)
hour_curve
Note how the plot options applied above to hour_curve
are remembered! The %%opts
magic is used to customize the object displayed as output for a particular code cell: behind the scenes HoloViews has linked the specified options to the hour_curve
object via a hidden integer id attribute.
Having used the %%opts
magic on hour_curve
again, we have now associated the 'red' color
style option to it. In the options specification syntax, style options are the keywords in parentheses and are keywords defined and used by Bokeh to style line glyphs.
In [ ]:
# Exercise: Display hour_curve without any new options to verify it stays red
In [ ]:
# Exercise: Try setting the line_width style options to 1
In [ ]:
# Exercise: Try setting the line_dash style option to 'dotdash'
In [ ]:
%%output backend='matplotlib'
hour_curve
All our options are gone! This is because the options are associated with the corresponding plotting extension---if you switch back to 'bokeh', the options will be applicable again. In general, options have to be specific to backends; e.g. the line_width
style option accepted by Bokeh is called linewidth
in matplotlib:
In [ ]:
%%output backend='matplotlib'
%%opts Curve [aspect=4 fig_size=400 xrotation=90] (color='blue' linewidth=2)
hour_curve
In [ ]:
# Exercise: Apply the matplotlib equivalent to line_dash above using linestyle='-.'
%output
line magicIn the two cells above we repeated %%output backend='matplotlib'
to use matplotlib to render those two cells. Instead of repeating ourselves with the cell magic, we can use a "line magic" (similar syntax to the cell magic but with one %
) to set things globally. Let us switch to matplotlib with a line magic and specify that we want SVG output:
In [ ]:
%output backend='matplotlib' fig='svg'
Unlike the cell magic, the line magic doesn't need to be followed by any expression and can be used anywhere in the notebook. Both the %output
and %opts
line magics set things globally so it is recommended you declare them at the top of your notebooks. Now let us look at the SVG matplotlib output we requested:
In [ ]:
%%opts Curve [aspect=4 fig_size=400 xrotation=70] (color='green' linestyle='--')
hour_curve
In [ ]:
# Exercise: Verify for yourself that the output above is SVG and not PNG
# You can do this by right-clicking above then selecting 'Open Image in a new Tab' (Chrome) or 'View Image' (Firefox)
In previous releases of HoloViews, it was typical to switch to matplotlib in order to export to PNG or SVG, because Bokeh did not support these file formats. Since Bokeh 0.12.6 we can now easily use HoloViews to export Bokeh plots to a PNG file, as we will now demonstrate:
In [ ]:
%output backend='bokeh'
By passing fig='png'
and a filename='eclipses'
to %output
we can both render to PNG and save the output to file:
In [ ]:
%%output fig='png' filename='eclipses'
hour_curve.clone()
Here we have requested PNG format using fig='png'
and that the output is output to eclipses.png using filename='eclipses'
:
In [ ]:
ls *.png
Bokeh also has some SVG support, but it is not yet exposed in HoloViews.
The above examples showed how to customize by type, but HoloViews offers multiple additional levels of customization that should be sufficient to cover any purpose. For our last example, let us split our eclipse dataframe based on the type ('Total' or 'Partial'):
In [ ]:
total_eclipses = eclipses[eclipses.type=='Total']
partial_eclipses = eclipses[eclipses.type=='Partial']
In [ ]:
%opts Spikes [width=900 yaxis=None]
Now let us look at the hour of day at which these two types of eclipses occur (local time) by overlaying the two types of eclipse as Spikes
elements. The problem then is finding a way to visually distinguish the spikes corresponding to the different ellipse types.
We can do this using the element group
and label
introduced in the introduction to elements section as follows:
In [ ]:
%%opts Spikes.Eclipses.Total (line_dash='solid')
%%opts Spikes.Eclipses.Partial (line_dash='dotted')
total = hv.Spikes(total_eclipses, kdims=['hour_local'], vdims=[], group='Eclipses', label='Total')
partial = hv.Spikes(partial_eclipses, kdims=['hour_local'], vdims=[], group='Eclipses', label='Partial')
(total * partial).redim.label(hour_local='Local time (hour)')
Using these options to distinguish between the two categories of data with the same type, you can now see clear patterns of grouping between the two types, with many more total eclipses around noon in local time. Similar techniques can be used to provide arbitrarily specific customizations when needed.
In [ ]:
# Exercise: Remove the two %%opts lines above and observe the effect
In [ ]:
# Exercise: Show all spikes with 'solid' line_dash, total eclipses in black and the partial ones in 'lightgray'
In [ ]:
# Optional Exercise: Try differentiating the two sets of spikes by group and not label
We have now seen some of the ways you can customize the appearance of your visualizations. You can consult our Customizing Plots user guide to learn about other approaches, including the hv.opts
and hv.output
utilities which do not rely on notebook specific syntax. One last approach worth mentioning is the .opts
method which accepts a customization specification dictionary or string to customize a particular object directly. When called without any arguments .opts()
clears any customizations that may be set on that object.
In the exploration with containers section that follows, you will also see a few examples of how the appearance of elements can be customized when viewed in containers.