Customizing HoloViews

Introduction

This is another exploration - this time looking at what they call Customization. In my introduction post when I made a scatter plot with a hover tool I first had to make the Scatter element and then add the hover tool as part of the options. HoloViews does this to try and emphasize a separation of content and presentation. When making the Scatter element I was supposed to only be thinking about the data that I wanted to add, then when working with the options I was turning to focus on the aesthetics.

Set Up

Imports

Python

from datetime import datetime
from functools import partial
from pathlib import Path
import os

PyPi

Related Projects

from neurotic.tangles.timer import Timer

This Project

from bartleby_the_penguin.tangles.embed_bokeh import EmbedBokeh

The Timer

TIMER = Timer()

The Embedder

files_path = Path("../../files/posts/libraries/customizing-holoviews/")
Embed = partial(
    EmbedBokeh,
    folder_path=files_path)

Bokeh Backend

When I ran the code further down in the notebook to render the javascript I was getting this error:

ValueError: autoload_static expects a single Model or Document

It was because I forgot the next step and it was defaulting to Matplotlib for some reason.

holoviews.extension("bokeh")

The Data

load_dotenv(".env")
path = Path(os.environ.get("PORTLAND_CRIME")).expanduser()
assert path.exists()
with TIMER:
    data = pandas.read_csv(path)
Started: 2019-03-02 14:25:02.818262
Ended: 2019-03-02 14:25:03.296873
Elapsed: 0:00:00.478611
print(data.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 217224 entries, 0 to 217223
Data columns (total 17 columns):
Address              196626 non-null object
Case Number          217224 non-null object
Crime Against        217224 non-null object
Neighborhood         210788 non-null object
Number of Records    217224 non-null int64
Occur Month Year     217224 non-null object
Occur Date           217224 non-null object
Occur Time           217224 non-null int64
Offense Category     217224 non-null object
Offense Count        217224 non-null int64
Offense Type         217224 non-null object
OpenDataLat          193352 non-null float64
OpenDataLon          193352 non-null float64
OpenDataX            193352 non-null float64
OpenDataY            193352 non-null float64
Report Date          217224 non-null object
ReportMonthYear      217224 non-null object
dtypes: float64(4), int64(3), object(10)
memory usage: 28.2+ MB
None
date = (data["Occur Date"]
        + " "
        + data["Occur Time"].astype(str).str.zfill(4))
data["date"] = pandas.to_datetime(date, format="%m/%d/%Y %H%M")

print(data.date[:5])
0   2017-08-26 00:00:00
1   2017-08-29 16:00:00
2   2017-08-12 19:00:00
3   2017-08-27 01:00:00
4   2017-07-24 09:03:00
Name: date, dtype: datetime64[ns]
data = data[(data.date >= datetime(2015, 5, 31))
            & (data.date < datetime(2019, 1, 1))]
selection = data[data.date > datetime(2018, 12, 24)].sort_values("date")

Plot time vs Latitude.

First we get our content.

curve = holoviews.Curve(selection, ("date", "Date-Time"), ("OpenDataLat", "Latitude"))
timestamps = holoviews.Spikes(selection, ("date", "Date-Time"), [])
layout = curve + timestamps

Now we make our presentation.

Take Two

Although the defaults give us a plot that's hard to read, by adjusting the width of the plot we can make it something more interpretable.

layout = layout.opts(
    opts.Curve(height=200, width=900, xaxis=None, color="red", line_width=1.5, tools=["hover"]),
    opts.Spikes(height=150, width=900, xaxis=None, color="grey")
).cols(1)