---
output:
bookdown::html_document2
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
# load cleaned data
d <- readRDS("rides_weather.rds")
```
```{=html}
```
::: {.gridlayout}
::: {.title}
Explore conditions of January, CitiBike
ridership for segmentation and targeting.
:::
::: {.instructions}
[How to explore :]{style="color: #000000; font-weight: 900;"} **Hovering** over any line will link the four variables --- *weather*, *rides per minute*, *average age*, and *percent female* --- and identify the *date* and *weekday* selected. [Quick takes :]{style="color: #000000; font-weight: 900;"} The morning and evening weekday peak commutes stand out from weekends, of course. But more interestingly, on New Year's Day, our warmest of the month, you'll find a significant swing in average age `r sparkline::sparkline(round(d$avg_age[d$date=="2019-01-01"], digits = 0 ), lineColor = "black", fillColor = NA, lineWidth = 3)` as [night]{style="background:#eeeeee;"} became morning; were our younger commuters out late, sleeping in? Below are ***smoothed functions*** of the data.
:::
::: {.lefttoptext}
Do rider **attributes** correlate with lower usage? Are we missing key target audiences?
:::
::: {.righttoptext}
Are there better **temperatures** for us to trigger marketing messages to encourage rides?
:::
::: {.leftbottomtext}
How can we **segment** our audience to find opportunities for increasing ridership?
:::
::: {.rightbottomtext}
Are there better **times of day** for us to trigger marketing messages to encourage rides?
:::
::: {.citesource}
The lines show cubic splines, smoothing variation of each variable over the day. Sources: NYC Open Data,
The Open Bus project, and Weather Underground. 2019 January 1-31. Design and code by Scott Spencer. 2021 March 31.
:::
::: {.rightinteractive}
```{r}
# we loaded the data d in the top code chunk of this file
# here are the libraries and default theme settings
library(ggplot2)
library(ggthemes)
theme_set(
theme_tufte(
base_family = "sans",
base_size = 16/.pt) +
theme(axis.ticks = element_blank(),
axis.text = element_text(face = "bold")))
library(patchwork)
library(ggiraph)
# save ggplot of rides per minute ~ time of day | date
p_riderate <-
ggplot(d) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("00:50:00"),
xmax = hms::as_hms("07:20:00"),
ymin = 0,
ymax = 61
),
fill = "#efefef"
) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("16:48:00"),
xmax = hms::as_hms("24:00:00"),
ymin = 0,
ymax = 61
),
fill = "#efefef"
) +
geom_smooth_interactive(
mapping = aes(
x = time_weather,
y = rides_minute,
group = date,
data_id = date,
# this was a quick and dirty approach to making a tooltip, but is ugly and the code is duplicated four times (for four plots)
# making one with package flextable would be much better
# https://ardata-fr.github.io/flextable-book/index.html
# google for how it's used in this context
tooltip = paste(
paste0('', format(as.Date(date), '%A %B %d'), ''),
paste0('Daily averages
Temperature, ', round(daily_avg_temp, digits = 0)),
paste0('Rides / minute, ', round(daily_avg_rate, digits = 0)),
paste0('Age, ', round(daily_avg_age, digits = 0)),
paste0('Percent female, ', round(daily_frac_female * 100, digits = 0)),
sep = '\n'
)),
se = F,
color = "black",
size = 0.3,
method = "gam",
formula = y ~ s(x, bs = "cs")) +
scale_x_time(name = "",
breaks = NULL,
expand = c(0,0)) +
scale_y_continuous(name = "Rides / minute")
# save ggplot of rides per minute ~ time of day | date
p_temp <-
ggplot(d) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("00:50:00"),
xmax = hms::as_hms("07:20:00"),
ymin = 0,
ymax = 61
),
fill = "#efefef"
) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("16:48:00"),
xmax = hms::as_hms("24:00:00"),
ymin = 0,
ymax = 61
),
fill = "#efefef"
) +
geom_smooth_interactive(
mapping = aes(
x = time_weather,
y = avg_temp,
group = date,
data_id = date,
tooltip = paste(
paste0('', format(as.Date(date), '%A %B %d'), ''),
paste0('Daily averages
Temperature, ', round(daily_avg_temp, digits = 0)),
paste0('Rides / minute, ', round(daily_avg_rate, digits = 0)),
paste0('Age, ', round(daily_avg_age, digits = 0)),
paste0('Percent female, ', round(daily_frac_female * 100, digits = 0)),
sep = '\n'
)),
se = F,
color = "black",
size = 0.3,
method = "gam",
formula = y ~ s(x, bs = "cs")) +
scale_x_time(name = "",
breaks = NULL,
expand = c(0,0)) +
scale_y_continuous(name = "Weather, degrees F")
# save ggplot of average age ~ time of day | date
p_age <-
ggplot(d) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("00:50:00"),
xmax = hms::as_hms("07:20:00"),
ymin = 34,
ymax = 45
),
fill = "#efefef"
) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("16:48:00"),
xmax = hms::as_hms("24:00:00"),
ymin = 34,
ymax = 45
),
fill = "#efefef"
) +
geom_smooth_interactive(
mapping = aes(
x = time_weather,
y = avg_age,
group = date,
data_id = date,
tooltip = paste(
paste0('', format(as.Date(date), '%A %B %d'), ''),
paste0('Daily averages
Temperature, ', round(daily_avg_temp, digits = 0)),
paste0('Rides / minute, ', round(daily_avg_rate, digits = 0)),
paste0('Age, ', round(daily_avg_age, digits = 0)),
paste0('Percent female, ', round(daily_frac_female * 100, digits = 0)),
sep = '\n'
)),
se = F,
color = "black",
size = 0.3,
method = "gam",
formula = y ~ s(x, bs = "cs")) +
scale_x_time(name = "",
breaks = NULL,
expand = c(0,0)) +
scale_y_continuous(name = "Average age")
# save ggplot of fraction female ~ time of day | date
p_female <-
ggplot(d) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("00:50:00"),
xmax = hms::as_hms("07:20:00"),
ymin = 0,
ymax = 35
),
fill = "#efefef"
) +
geom_rect(
mapping = aes(
xmin = hms::as_hms("16:48:00"),
xmax = hms::as_hms("24:00:00"),
ymin = 0,
ymax = 35
),
fill = "#efefef"
) +
geom_smooth_interactive(
mapping = aes(
x = time_weather,
y = frac_female * 100,
group = date,
data_id = date,
tooltip = paste(
paste0('', format(as.Date(date), '%A %B %d'), ''),
paste0('Daily averages
Temperature, ', round(daily_avg_temp, digits = 0)),
paste0('Rides / minute, ', round(daily_avg_rate, digits = 0)),
paste0('Age, ', round(daily_avg_age, digits = 0)),
paste0('Percent female, ', round(daily_frac_female * 100, digits = 0)),
sep = '\n'
)),
se = F,
color = "black",
size = 0.3,
method = "gam",
formula = y ~ s(x, bs = "cs")) +
scale_x_time(name = "Time of day",
breaks = scales::date_breaks("60 mins"),
labels = seq(0, 24),
expand = c(0,0)) +
scale_y_continuous(name = "Percent Female",
breaks = seq(0, 35, by = 10),
expand = c(0,0))
# here we bind those interactive layers to css and svg elements using
# package ggiraph and this function. Notice the forward slashes are
# functions from the patchwork package
# can add animation, e.g., transition:0.5s ease-in-out;
girafe(
code = print(p_temp / p_riderate / p_age / p_female),
options = list(
opts_hover(css = "stroke-width:2;"),
opts_hover_inv(css = "stroke-opacity:0.1;"),
opts_tooltip(
css = 'background-color:white;color:black;font-size:8pt;padding:10px;',
offx = 10,
offy = 10
),
opts_toolbar(saveaspng = FALSE)
))
```
:::
:::