Customizing HoloViews
Table of Contents
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)