---
title: "Aggregating data spatially, and making glyph maps"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{aggregation}
  %\usepackage[utf8]{inputenc}
  %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  chunk_output_type: console
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  warning = FALSE, 
  message = FALSE,
  out.width = "100%"
)
library(dplyr)
library(cubble)
library(ggplot2)
library(sf)
```

Global Historical Climatology Network (GHCN) provides daily climate measures from stations across the world. `prcp_aus` extracts daily precipitation and minimum temperature from GHCN for 639 stations in Australia from 2016 to 2020. This is where these stations locate in an Australia map: 

```{r}
state_map <- st_simplify(ozmaps::abs_ste, dTolerance = 4000)
ggplot() + 
  geom_sf(data = state_map, inherit.aes = FALSE,
          color = "grey80", alpha = 0.4, linetype = 3) +
  geom_point(data = prcp_aus , aes(x = long, y = lat)) + 
  theme_void()
```

This is a lot of stations to look at for one climate variable and they can't all fit into a glyph map. What we can do is to group stations into clusters and look at the aggregated series in the glyph map. In this vignette, I will introduce how to perform aggregation using a hierarchical data structure in cubble. 

First, let's summarise the daily data into weekly sum for each station:

```{r}
prcp_aus
```

First we need to assign each station a cluster number. Here we use a simple kmean algorithm based on the distance matrix to create 20 clusters. This creates `station_nested` as a station level nested cubble with a cluster column indicating the group each station belongs to.

```{r echo = FALSE}
coords <- cbind(prcp_aus$long, prcp_aus$lat)
dist_raw <- geosphere::distm(coords, coords)

set.seed(123)
station_nested <- prcp_aus %>%  
  strip_rowwise() %>%  
  mutate(cluster = kmeans(dist_raw,centers = 20, nstart = 500)$cluster)
```

```{r}
station_nested
```

To create a group level cubble, use `switch_key()` with the new key variable, `cluster`:

```{r}
cluster_nested <- station_nested %>%  switch_key(cluster)
cluster_nested %>%  head(5)
```

The resulted `cluster_nested` now has `cluster` as the key and all the station level time invariant variables are nested inside `.val`. Currently, there is no cluster level time invariant variables and we can add the centroid of each cluster by `get_centroid()`: 

```{r}
(cluster_nested <- cluster_nested %>%  get_centroid())
```

You can also use `face_temporal()` to get the cluster level long cubble:

```{r}
(cluster_long <- cluster_nested %>%  face_temporal(ts))
```

Now we should have access to  both station and cluster level in the nested and long form. Let's summarise them within a diagram:

```{r echo = FALSE, out.height="110%"}
knitr::include_graphics("cluster-diagram/cluster-diagram.png")
```

With these data, we can make a glyph map to understand the precipitation pattern in Australia:

```{r echo = FALSE}
cluster_long <- cluster_nested %>%  
  face_temporal() %>%  
  group_by(wk) %>%  
  summarise(prcp = mean(prcp, na.rm = TRUE)) %>%  
  unfold(cent_long, cent_lat)

state_map <- st_simplify(ozmaps::abs_ste, dTolerance = 4000)

ggplot_smooth <- cluster_long %>%  
  ggplot() +
  geom_smooth(aes(x = wk, y = prcp, group = cluster), span = 0.4) 

smoother <- layer_data(ggplot_smooth) %>%  
  left_join(cluster_long %>%  select(cluster, cent_long, cent_lat), by = c("group" = "cluster"))

ggplot(data = smoother, 
       aes(x_minor = x, y_minor = y, 
           x_major = cent_long, y_major = cent_lat)) + 
  geom_sf(data = state_map, inherit.aes = FALSE, 
          color = "grey80", alpha = 0.4, linetype = 3) + 
  geom_text(data = cluster_nested, 
            aes(x = cent_long, y = cent_lat, label = cluster), 
            inherit.aes = FALSE) +
  geom_glyph(height = 2, width = 4) + 
  theme_void()
```

Or to inspect the station membership of each cluster:

```{r}
ggplot() + 
  geom_sf(data = state_map, inherit.aes = FALSE,
          color = "grey80", alpha = 0.4, linetype = 3) +
  geom_point(data = station_nested, aes(x = long, y = lat), size = 0.5) +
  ggforce::geom_mark_hull(
    data = cluster_nested %>% tidyr::unnest(hull),
    expand = 0, radius = 0,
    aes(x = long, y = lat, group = cluster)) + 
  theme_void()
```

