Interactive graphics can be useful when working with spatio-temporal
data since they allow for exploring the data from multiple perspective.
In this vignette, we will demonstrate how to create an interactive
graphic with cubble objects. We will be using
crosstalk::bscols()
to create a linked interactive plot of
an Australia map, created with leaflet, and a ggplot plotly time series
plot:
Australia has diverse climate conditions with different temperature
patterns across its regions. and different temperature patterns can be
observed. We can compute the average maximum and minimum temperature by
month at 30 locations sampled from the dataset climate_aus
.
The diurnal temperature range, the difference between the maximum and
minimum temperature, has different variations throughout the year. We
will use its variance to color the plot. The codes below calculate these
variables:
set.seed(123)
climate_smaller <- climate_aus |> head(n = 30)
(clean <- climate_smaller |>
face_temporal() |>
group_by(month = lubridate::month(date, label = TRUE, abbr = TRUE)) |>
summarise(
tmax = mean(tmax, na.rm = TRUE),
tmin = mean(tmin, na.rm = TRUE),
diff = mean(tmax - tmin, na.rm = TRUE)
) |>
face_spatial() |>
rowwise() |>
mutate(temp_diff_var = var(ts$diff, na.rm = TRUE))
)
#> # cubble: key: id [30], index: month, nested form
#> # spatial: [113.53, -25.93, 128.71, -13.75], Missing CRS!
#> # temporal: month [ord], tmax [dbl], tmin [dbl], diff [dbl]
#> id long lat elev name wmo_id ts temp_diff_var
#> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <list> <dbl>
#> 1 ASN00001006 128. -15.5 3.8 wyndham aero 95214 <gropd_df> 8.65
#> 2 ASN00001007 126. -13.8 6 troughton isla… 94102 <gropd_df> 0.258
#> 3 ASN00001018 126. -16.4 546 mount elizabeth 94211 <gropd_df> 23.4
#> 4 ASN00001019 127. -14.3 23 kalumburu 94100 <gropd_df> 18.7
#> 5 ASN00001020 126. -14.1 51 truscott 95101 <gropd_df> 5.90
#> 6 ASN00001025 126. -15.4 385 doongan 94215 <gropd_df> 16.0
#> 7 ASN00002012 128. -18.2 422 halls creek ai… 94212 <gropd_df> 7.27
#> 8 ASN00002032 128. -17.0 203 warmun 94213 <gropd_df> 3.58
#> 9 ASN00002056 129. -15.8 44 kununurra aero 94216 <gropd_df> 8.65
#> 10 ASN00002064 128. -16.6 164 argyle aerodro… 94217 <gropd_df> 2.81
#> # ℹ 20 more rows
We create two SharedData objects in crosstalk - one using the nested
cubble and another using the long cubble. We will use the
id
as the key and give them the same group name
(group = "cubble"
):
nested <- clean |> SharedData$new(~id, group = "cubble")
long <- clean |>
face_temporal() |>
unfold(temp_diff_var) |>
arrange(temp_diff_var) |>
SharedData$new(~id, group = "cubble")
To create a basic leaflet map showing station location, we can use
addTiles()
to create an underlying map and
addCircleMarkers()
to add points representing the
stations:
leaflet(nested, width = 300, height = 300) |>
addTiles() |>
addCircleMarkers()
To apply colors to the stations, we need to map a variable in the
data to a color palette. In this example, we map the numerical variable
temp_diff_var
to a sequential color palette, Rocket, with
some color fine-tuning using colorNumeric()
. We also add a
popup to display the station names using the popup
argument
in addCircleMarkers()
:
domain <- clean$temp_diff_var
pal <- colorNumeric(
colorspace::sequential_hcl(
"Rocket", n = 7, cmax = 90, rev = TRUE, c2 = 40, l2= 85, c1 = 20, l1 = 30),
domain = domain)
map <- leaflet(nested, width = 300, height = 300) |>
addTiles() |>
addCircleMarkers(color = ~pal(domain), group = "a", radius = 0.1,
popup = ~name, fillOpacity = 1, opacity = 1)
The time series plot allows us to visualize the temperature band of each station, providing insights into the diurnal temperature range by month. We can use geom_ribbon() to create a temperature band that displays both the maximum and minimum temperature:
ts_static <- long |>
ggplot(aes(x = month, group = id,
fill = temp_diff_var, color = temp_diff_var
)) +
geom_ribbon(aes(ymin = tmin, ymax = tmax), size = 0.1, alpha = 0.3) +
# geom_point(aes(y = tmax), size = 0.1) +
# geom_point(aes(y = tmin), size = 0.1) +
colorspace::scale_fill_continuous_sequential(
"Rocket", n_interp = 7, cmax = 90, rev = TRUE,
c2 = 40, l2= 85, c1 = 20, l1 = 30, name = "Var. temp. diff.") +
colorspace::scale_colour_continuous_sequential(
"Rocket", n_interp = 7, cmax = 90, rev = TRUE,
c2 = 40, l2= 85, c1 = 20, l1 = 30, name = "Var. temp. diff.") +
labs(x = "Month", y = "Temperature") +
theme_bw() +
theme(
panel.grid.major = element_blank(),
legend.position = "bottom"
)
The static ggplot object can be converted into a plotly object using
ggplotly()
and plotly::highlight()
enable the
box or lasso selection (on = "plotly_selected"
):
ts_interactive <- ggplotly(ts_static, width = 600, height = 300) |>
highlight(on = "plotly_selected", opacityDim = 0.012)
crosstalk::bscols()
combines multiple interactive
graphics in columns:
bscols(map, ts_interactive, widths = c(4, 6))
Below is a screenshot of the full graphics:
The selection in the linked plot works in both directions. In the screenshot below, a lasso selection is made on the time series, linking to the Cygnet Bay on the northwest coastline of Australia. In July, this area shows a larger temperature range compared to the summer period (December - February).
Selection on the leaflet map can be made using the selection tool below the zoom-in/out bottom on the map. In the screenshot, two selections are made - one on northern Australia and the other in inland Queensland. Northern Australia has a narrow temperature range constantly 20 degrees throughout the year, while inland Queensland temperature has a much larger temperature range with a noticeable difference between the summer and winter periods.
Now it is your time to view the tooltip on the map and use the selection to explore weather patterns in Australia!