Skip to main content

Section 6.3 Visualising time data

Once we have parsed and cleaned the temporal information that is available in our date variable, we can make use of this to visualise trends in other ways, not just using time series. For example, we might want to show where hot spots in time occur, within a year, or within a week, or some other set interval. One approach for this is to use a calendar heatmap. First, we create a column for date, removing the time (hour, minute and second). We can achieve this easily by using the date() function in lubridate:
agassault_ny$date <- date(agassault_ny$date_single)
If we have a look, we can now see that the time component has been stripped away, and we have this date object. Let’s look at the value for the first row.
agassault_ny$date[1]
## [1] "2014-01-01"
That looks like what we are expecting. Now let’s see the class of this variable.
class(agassault_ny$date)
## [1] "Date"
It is a date object, so we will be able to do date-time operations to it. Now what we want to do is create a heatmap, a sort of calendar, of the number of aggravated assault incidents per date. We can use our well-known attribute operations here, specifically the group_by() function in the dplyr package to count the events per day.
agassault_ny_d <- agassault_ny %>%
                    group_by(date) %>% summarise(assaults = n())
Now we have this new dataframe, the number of aggravated assaults per day. To make our temporal heatmap calendar, we will now use a ggplot2 extension, ggTimeSeries, that allows us to produce calendar heat visualisations. In this package, we can use the ggplot_calendar_heatmap() function, which creates a calendar heatmap. This approach provides context for weeks, and day of week which makes it a better way to visualise daily data than line charts.
library(ggTimeSeries)

ggplot_calendar_heatmap(
   agassault_ny_d,  # our dataset of dates and number of crimes
   cDateColumnName = 'date', # column name of the dates
   cValueColumnName = 'assaults') + # column name of the data
   xlab(NULL) + # x axis lable
   ylab(NULL) + # y axis lable
   scale_fill_continuous(low = '#f7fcfd',  # set colour for low count
                         high = '#6e016b') +   # set colour for high count
  facet_wrap(~Year, ncol = 1) +  # separate out by each year
  theme_minimal()
With one row per year, labeled with each year from 2014 to 2018, a grid of shaded squares appears. Each of the five grids is seven cells tall, with labels at the left clarifying them as days Monday, Tuesday, and so on to Sunday. Thick lines in the grid separate the months horizontally, and there are enough cells to cover each year. To the right of these grids, a legend labeled ’assaults’ matches a gradient from purple to white with numbers from one hundred twenty five down to twenty five. In general, each year the summer months are shaded darker, and the weekends look darker than the weeks. Some notable days, such as new years’ are also darker.
Figure 6.3.1. Calendar heat map of aggravated assaults
This sort of visualisation might be useful for example to see if certain days of the week have more incidents than others, possibly due to differences in the underlying routine activities that predominate for example weekends versus weekdays. For a bit of fun, you can read [Moss (2013)] for a safety rating on each day of the week.

Subsection 6.3.1 How (not) to present time

In our calendar heatmap, above we presented count of crimes on each day. But there are other approaches to visualise change over time as well. One such approach is to present percentage change from one point in time to the next. There are many issues with this approach, which lead to misinterpreting the data, which are explored in detail by [Wheeler (2016)]. For example, he mentions that percentage change is not symmetric: "For example, an increase from 4 to 5 crimes is a 25% increase, whereas a decrease from 5 to 4 crimes is only a 20% decrease" (p.x). He presents an alternative metric in Poisson z-scores.
Another issue is with the very popular approach of showing changes as year-to-date. In the post: "Why you can’t identify changes in crime by comparing this month to last month," [Ashby (2020)] presents some great arguments for why attempts to identify changes in crime frequency that involve simply comparing the number of crimes this week/month/year to the number that occurred last week/month/year, or comparing this week, month, etc. to the same period last year is not an appropriate way to analyse change over time. For example, doing this means throwing away useful information, ignoring trends and seasonality, and leaves results vulnerable to noise. As an alternative, he promotes the use of creating a forecast based on historic data, and comparing observed values against this. It is important that when presenting temporal data, we keep in mind these notes of caution, and follow good practice recommendations such as those notes here.