Date: 2026-01-23

# Tasmania

#### 2026-01-23

    library(sugarbag)
    library(dplyr)
    library(tidyr)
    library(tibble)
    library(ggplot2)
    library(sf)

## Creating a hexagon map of Tasmania

Tasmania is the southern-most state of Australia, it has one large land mass and several smaller islands.

### Data

We will use the Australian Bureau of Statistics’ ESRI shape files to build our map.

The set has been filtered for only Tasmanian areas. The data set of Tasmanian Statistical Areas at level two has been provided in the `sugarbag` package.

Alternatively the data can be created from the set of Australian areas using the following code:

    library(strayr)
    strayr::sa22016 %>%
      filter(state_name_2016 == "Tasmania") %>%
      # convert to long lat
      st_transform(., crs = "+proj=longlat +ellps=GRS80")

### Centroids

The function `create_centroids` finds the central points of the polygons provided as an argument.

    # Find the longitude and latitude centroid for each region or area
    centroids <- create_centroids(tas_sa2, sf_id = "sa2_name_2016")

### Hexagon grid

To tessellate correctly, all the hexagons must be evenly spaced. This function creates a grid of possible locations for the polygons.

    grid <- create_grid(centroids = centroids, hex_size = 0.2, buffer_dist = 1.2)

The `sugarbag` package operates by creating a grid of possible hexagons to allocate electorates. The buffer extends the grid beyond the geographical space, this is especially useful for densely populated coastal areas or cities, such as Brisbane and Sydney in this case, Hobart.

### Allocate areas

Each polygon centroid will be allocated to the closest available hexagon grid point. The capital cities data set will be used to preserve neighbourly relationships. The `allocate` function requires two inputs, the centroids and the grid.

    # Allocate the centroids to the hexagon grid
    # We have the same amount of rows, as individual regions
    hex_allocated <- allocate(centroids = centroids,
                              sf_id = "sa2_name_2016",
                              hex_grid = grid,
                              hex_size = 0.2, # same size used in create_grid
                              hex_filter = 10,
                              focal_points = capital_cities,
                              # same column used in create_centroids
                              width = 30, verbose = TRUE)
    #> Finding closest point in focal_points data set.
    #> Allocating centroids, in order of distance to closest focal point.

The function `fortify_hexagon` assists in plotting. We now have 6 points per region, one for each point of a hexagon. Connecting these points will allow actual hexagons to be plotted.

The additional demographic information or data can now be added. This can be used to allow plots to be coloured by region.

For animations to move between geography and hexagons the `sf_id` must match, there also needs to be an identifier to separate the states to animate between for `gganimate`.

    hexagons <- hex_allocated %>%
      fortify_hexagon(hex_size = 0.2, sf_id = "sa2_name_2016") %>%
      left_join(., tas_sa2) %>%
      mutate(poly_type = "hex")
    #> Joining with `by = join_by(sa2_name_2016)`

    polygons <- fortify_sfc(tas_sa2) %>%
      mutate(poly_type = "geo")

    ggplot(mapping = aes(fill = sa4_name_2016)) +
      geom_polygon(data = polygons, aes(x=long, lat, group = interaction(sa2_name_2016,polygon)), alpha = 0.4) +
      geom_polygon(data = hexagons, aes(x=long, lat, group = interaction(sa2_name_2016))) + scale_fill_viridis_d()

    hexagon_points <- hexagons %>%
      select(sa4_name_2016, sa2_name_2016,
    sa2_name_2016, long, lat, poly_type) %>%
      left_join(polygons %>% distinct(sa2_name_2016, polygon), by = "sa2_name_2016")
    #> Warning in left_join(., polygons %>% distinct(sa2_name_2016, polygon), by = "sa2_name_2016"): Detected an unexpected many-to-many relationship between `x` and `y`.
    #> ℹ Row 31 of `x` matches multiple rows in `y`.
    #> ℹ Row 183 of `y` matches multiple rows in `x`.
    #> ℹ If a many-to-many relationship is expected, set `relationship =
    #>   "many-to-many"` to silence this warning.
    polygon_points <- polygons %>%
      select(sa4_name_2016, sa2_name_2016, long, lat, polygon, poly_type)

    animate_tas <- bind_rows(hexagon_points, polygon_points) %>%
      left_join(homeless, by = "sa2_name_2016")

    animate_tas %>%
      ggplot(aes(x=long, y=lat, group = interaction(polygon, sa2_name_2016))) +
      geom_polygon(aes(fill = sa4_name_2016)) +
      geom_polygon(data = polygon_points %>% select(-poly_type), fill = "grey40", alpha = 0.05) +
      coord_equal() +
      theme_void() +
      guides(fill = guide_legend(title = NULL)) +
      theme(legend.position = "bottom") +
      facet_wrap(~poly_type) +
      scale_fill_viridis_d()

Creating an animation requires additional packages.

Consider installing: - the `transformr` package to tween (go between) polygons - the `gifski` package for gif output - the `ava` package for video output

    library(gganimate)
    library(transformr)

    animation <- animate_tas %>%
      ggplot(aes(x=long, y=lat, group = interaction(polygon, sa2_name_2016))) +
      geom_polygon(aes(fill = sa4_name_2016)) +
      geom_polygon(data = polygon_points %>% select(-poly_type), fill = "grey40", alpha = 0.05) +
      coord_equal() +
      theme_void() +
      guides(fill = guide_legend(title = NULL)) +
      theme(legend.position = "bottom") +
      transition_states(states = poly_type) +
      scale_fill_viridis_d()

    animated <- animate(animation, fps = 10, duration = 15,
                        start_pause = 5, end_pause = 5, rewind = FALSE)

    anim_save(filename = "tasmania_animation.gif", animated)