Overview
sugarglider
provides ggplot2 extensions to create glyph
maps that visualize multivariate spatio-temporal data with
geom_glyph_ribbon()
and
geom_glyph_segment()
.
These functions create a ribbon geometry designed to display glyphs
based on the combination of x_major
and
y_major
. For each x_minor
value,
geom_glyph_ribbon()
displays a y interval defined by
ymin_minor
and ymax_minor
. Meanwhile,
geom_glyph_segment()
draw a straight line between
y_minor
and yend_minor
with respect to
x_minor
.
Let’s compare geom_glyph_ribbon()
and
geom_glyph_segment()
:
vic_temp <- aus_temp |>
filter(id %in% c("ASN00026021", "ASN00085291", "ASN00084143"))
# Define a color palette
color_palette <- c("deepskyblue4", "coral3")
p1 <- vic_temp |>
ggplot(aes(x_major = long,
y_major = lat,
x_minor = month,
ymin_minor = tmin,
ymax_minor = tmax)) +
geom_sf(data = abs_ste |> filter(NAME == "Victoria"),
fill = "antiquewhite", color = "white", inherit.aes = FALSE) +
# Customize the size of each glyph box using the width and height parameters.
add_glyph_boxes(width = rel(2.5), height = rel(1.5),
color = color_palette[1]) +
add_ref_lines(width = rel(2.5), height = rel(1.5),
color = color_palette[1]) +
geom_glyph_ribbon(width = rel(2.5), height = rel(1.5),
color = color_palette[1], fill = color_palette[1]) +
# Theme and aesthetic
theme_glyph() +
labs(title = "geom_glyph_ribbon()") +
theme(plot.title = element_text(hjust = 0.5),
title = element_text(color = color_palette[1],
family = "mono"))
p2 <- vic_temp |>
ggplot(aes(x_major = long,
y_major = lat,
x_minor = month,
y_minor = tmin,
yend_minor = tmax)) +
geom_sf(data = abs_ste |> filter(NAME == "Victoria"),
fill = "antiquewhite", color = "white", inherit.aes = FALSE) +
# Customize the size of each glyph box using the width and height parameters.
add_glyph_boxes(width = rel(2.5), height = rel(1.5),
color = color_palette[2]) +
add_ref_lines(width = rel(2.5), height = rel(1.5),
color = color_palette[2]) +
geom_glyph_segment(width = rel(2.5), height = rel(1.5),
color = color_palette[2]) +
# Theme and aesthetic
theme_glyph() +
labs(title = "geom_glyph_segment()") +
theme(plot.title = element_text(hjust = 0.5),
title = element_text(color = color_palette[2]))
grid.arrange(p1, p2, ncol = 2)
Options
Options allow you to modify the behavior of sugarglider
to fit the specific needs of your figure. These are all global options
that affect every glyph.
Option | Default | Description |
---|---|---|
x_scale |
"identity" |
This function scales each set of minor values within a grid cell along the x-dimension. |
y_scale |
"identity" |
This function scales each set of minor values within a grid cell along the y-dimension. |
width |
ggplot2::rel(4) |
Width of the glyph. |
height |
ggplot2::rel(2.5) |
Height of the glyph. |
global_rescale |
TRUE |
Determines whether rescaling is applied globally across all glyphs or individually for each glyph |
Aesthetics
sugarglider
provides the same aesthetics for
geom_glyph_ribbon()
and geom_glyph_segment()
as those available in geom_ribbon()
or
geom_segment()
, while also introducing additional unique
options.
Option | Default | Description |
---|---|---|
colour |
"black" |
Color for line segments and borders. |
linewidth |
0.5 |
Width of the line for borders. |
linetype |
1 |
Style of the line for borders. |
fill |
"black" |
Color of the interior area of the geometries. |
alpha |
0.8 |
Transparency level of the glyphs. |
Examples
Monthly temperature across Australia
The National Oceanic and Atmospheric Administration (NOAA) provides
comprehensive weather data from numerous stations across Australia. The
aus_temp
dataset includes key climate variables, such as
precipitation and temperature, recorded at 29 different weather stations
throughout 2020.
head(aus_temp) |>
kable() |> kable_styling()
id | long | lat | month | tmin | tmax | prcp |
---|---|---|---|---|---|---|
ASN00001020 | 126.3867 | -14.09 | 1 | 253.4516 | 319.0000 | 163.87097 |
ASN00001020 | 126.3867 | -14.09 | 2 | 248.6786 | 322.6071 | 162.74074 |
ASN00001020 | 126.3867 | -14.09 | 3 | 253.6129 | 333.1935 | 42.00000 |
ASN00001020 | 126.3867 | -14.09 | 4 | 244.0357 | 340.9310 | 21.57143 |
ASN00001020 | 126.3867 | -14.09 | 5 | 220.4138 | 331.9333 | 0.00000 |
ASN00001020 | 126.3867 | -14.09 | 6 | 202.3667 | 310.9000 | 11.20000 |
Using the default rescaling parameters, we can visualize the
temperature data through geom_glyph_segment()
, alongside
geom_point()
elements that mark the location of each
weather station. Each segment glyph represents local climate data,
offering an intuitive way to explore temperature variations across
Australia.
The default identity
scaling function is applied to each
set of minor values within a grid cell. This method centers the glyphs
both vertically and horizontally based on the station’s coordinates and
adjusts the minor axes to fit within the interval [-1, 1]. This ensures
that the glyphs are appropriately sized to fit the desired
dimensions.
aus_temp |>
ggplot(aes(
x_major = long,
y_major = lat,
x_minor = month,
y_minor = tmin,
yend_minor = tmax)) +
geom_sf(data = abs_ste, fill = "antiquewhite",
inherit.aes = FALSE, color = "white") +
coord_sf(xlim = c(110,155)) +
# Add glyph box to each glyph
add_glyph_boxes(
width = 4,
height = 3) +
# Add points for weather station
geom_point(aes(x = long, y = lat,
color = "Weather Station")) +
# Customize the size of each glyph box using the width and height parameters.
geom_glyph_segment(
width = 4, height = 3,
aes(color = "Temperature")) +
# Theme and aesthetic
scale_color_manual(
values = c("Weather Station" = "firebrick",
"Temperature" = "black")) +
labs(color = "Data",
title = "Daily Temperature Variations Across Australian Weather Stations") +
theme_glyph()
So far, all the visualizations have used global rescaling (enabled by default), meaning the glyphs are sized relative to one another based on their data values. By disabling global rescaling, we can see the effects of local rescaling, where each glyph is resized based on its individual values.
- Local Rescale (global_rescale = FALSE): Each line segment’s length is determined by the local temperature range within a region, emphasizing regional differences in temperature patterns.
- Global Rescale (global_rescale = TRUE): Global temperature range determined the length of each line segment, ensuring that data range remain consistent across all region for easy comparison.
Below is a comparison between the local and global rescaling approaches:
# Global rescale
p1 <- aus_temp |>
ggplot(aes(
x_major = long,
y_major = lat,
x_minor = month,
y_minor = tmin,
yend_minor = tmax)) +
geom_sf(data = abs_ste, fill = "antiquewhite",
inherit.aes = FALSE, color = "white") +
coord_sf(xlim = c(110,155)) +
# Add glyph box to each glyph
add_glyph_boxes() +
# Add reference lines to each glyph
add_ref_lines() +
# Glyph segment plot with global rescale
geom_glyph_segment(global_rescale = TRUE) +
labs(title = "Global Rescale") +
theme_glyph()
# Local Rescale
p2 <- aus_temp |>
ggplot(aes(
x_major = long,
y_major = lat,
x_minor = month,
y_minor = tmin,
yend_minor = tmax)) +
geom_sf(data = abs_ste, fill = "antiquewhite",
inherit.aes = FALSE, color = "white") +
coord_sf(xlim = c(110,155)) +
# Add glyph box to each glyph
add_glyph_boxes() +
# Add reference lines to each glyph
add_ref_lines() +
# Glyph segment plot with local rescale
geom_glyph_segment(global_rescale = FALSE) +
labs(title = "Local Rescale") +
theme_glyph()
grid.arrange(p1, p2, ncol = 2)
Highlighting Temperature Changes with Color-Coded Glyph
Expanding on our temperature analysis, we now incorporate
precipitation data across Australia using
geom_glyph_ribbon()
. The glyphs are color-coded to
represent varying levels of rainfall, with reference lines and glyph
boxes enhancing clarity and allow for easy comparison of precipitation
level across the country.
prcp <- aus_temp |>
group_by(id) |>
mutate(prcp = mean(prcp, na.rm = TRUE)) |>
ggplot(aes(x_major = long, y_major = lat,
x_minor = month, ymin_minor = tmin,
ymax_minor = tmax,
fill = prcp, color = prcp)) +
geom_sf(data = abs_ste, fill = "antiquewhite",
inherit.aes = FALSE, color = "white") +
# Add glyph box to each glyph
add_glyph_boxes() +
# Add ref line to each glyph
add_ref_lines() +
# Add glyph ribbon plots
geom_glyph_ribbon() +
coord_sf(xlim = c(112,155)) +
# Theme and aesthetic
theme_glyph() +
scale_fill_gradientn(colors = c("#ADD8E6", "#2b5e82", "dodgerblue4")) +
scale_color_gradientn(colors = c( "#ADD8E6", "#2b5e82", "dodgerblue4")) +
labs(fill = "Percepitation", color = "Percepitation",
title = "Precipitation and Temperature Ranges Across Australia")
prcp
If you’re interested in comparing temperature trends across different
years for specific regions in Victoria, geom_glyph_ribbon()
provides a way to visualize how temperatures have evolved over time,
with each year distinguished by a different color for clarity.
fact <- historical_temp |>
filter(id %in% c("ASN00026021", "ASN00085291", "ASN00084143")) |>
ggplot(aes(color = factor(year), fill = factor(year),
group = interaction(year,id),
x_major = long, y_major = lat,
x_minor = month, ymin_minor = tmin,
ymax_minor = tmax)) +
geom_sf(data = abs_ste |> filter(NAME == "Victoria"),
fill = "antiquewhite", color = "white",
inherit.aes = FALSE) +
# Customized the dimension of each glyph with `width` and `height` parameters
add_glyph_boxes(width = rel(2),
height = rel(1.5)) +
add_ref_lines(width = rel(2),
height = rel(1.5)) +
geom_glyph_ribbon(alpha = 0.5,
width = rel(2),
height = rel(1.5)) +
labs(x = "Longitude", y = "Latitude",
color = "year", fill = "year",
title = "Temperature Trends in Selected Victorian Weather Stations") +
# Theme and aesthetic
theme_glyph() +
theme(legend.position.inside = c(.4,0)) +
scale_colour_wsj("colors6") +
scale_fill_wsj("colors6")
fact
Integrating Glyph Legends
To further enhance map readability, the
add_geom_legend()
function integrates a larger version of
one of the glyphs into the bottom left corner of the plot. This legend
helps users interpret the scale of the data.
In the example below, a series of glyph are created using
geom_glyph_ribbon()
and overlaid on a basemap to depict
daily temperature variations across Australian weather stations. A
legend is added through add_glyph_legend()
, allowing users
to easily interpret the range of daily temperature value based on a
randomly selected weather station. Since the legend data is drawn from a
single, randomly chosen station, it’s important for users to set a seed
for reproducibility to ensure consistent results.
set.seed(28493)
legend <- aus_temp |>
ggplot(aes(x_major = long, y_major = lat,
x_minor = month, ymin_minor = tmin,
ymax_minor = tmax)) +
geom_sf(data = abs_ste, fill = "antiquewhite",
inherit.aes = FALSE, color = "white") +
add_glyph_boxes(color = "#227B94") +
add_ref_lines(color = "#227B94") +
add_glyph_legend(color = "#227B94", fill = "#227B94") +
# Add a ribbon legend
geom_glyph_ribbon(color = "#227B94", fill = "#227B94") +
theme_glyph() +
labs(title = "Temperature Ranges Across Australia with Glyph Legend")
legend
Observations and Insights
Both the Geom Glyph Segment and Geom Glyph Ribbon provide valuable insights into seasonal temperature trends across Australia. Disabling global rescaling reveals that most weather stations follow similar curvature trends relative to their neighboring stations. However, with global rescaling enabled, it becomes apparent that coastal regions exhibit far less temperature variation overall.
Flight Variability at U.S. Airports with the Most Cancellations
The U.S. Department of Transportation (DOT) Bureau of Transportation Statistics monitors the on-time performance of domestic flights operated by major U.S. airlines. Each month, the DOT publishes the Air Travel Consumer Report, which provides a summary of on-time, delayed, canceled, and diverted flights.
This dataset, sourced from the Kaggle Airline Flight Delay and Cancellation data, has been processed and aggregated to show the minimum and maximum number of flights originating from the top 10 U.S. airports with the highest cancellation rates.
head(flights) |>
kable() |> kable_styling()
origin | month | long | lat | min_flights | max_flights |
---|---|---|---|---|---|
ATL | 1 | -84.42806 | 33.63667 | 2321 | 3279 |
ATL | 2 | -84.42806 | 33.63667 | 1953 | 3074 |
ATL | 3 | -84.42806 | 33.63667 | 2667 | 3476 |
ATL | 4 | -84.42806 | 33.63667 | 896 | 3361 |
ATL | 5 | -84.42806 | 33.63667 | 785 | 3441 |
ATL | 6 | -84.42806 | 33.63667 | 1119 | 3473 |
In this section of the analysis, we will showcase the functionality
of geom_glyph_segment()
the monthly range of flights for
each airport, providing insights into how flight numbers fluctuate over
time. Additionally, we will use geom_glyph_ribbon()
to
visualize the variation between the minimum and maximum number of
flights from each airport.
USmap <- us_map(regions = "state") |>
filter(full != "Alaska")
# Specify tooltip for ggiraph
flights <- flights |>
mutate(tooltip = paste("origin: ",origin,
"\nmonth: ", month,
"\nmin_flights: ", min_flights,
"\nmax_flights: ", max_flights))
fl <- flights |>
ggplot(aes(x_major = long, y_major = lat,
x_minor = month, y_minor = min_flights,
yend_minor = max_flights,
tooltip = tooltip)) +
geom_sf(data = USmap, color = "white",
fill = "antiquewhite", inherit.aes = FALSE) +
coord_sf(crs = st_crs(4326)) +
add_glyph_boxes(color = "#CD5C08") +
add_ref_lines(color = "#CD5C08") +
geom_glyph_segment(color = "#CD5C08") +
labs(title = "Monthly Flight Variability",
subtitle = "Based on top 10 US Airports with high cancellations rate") +
theme_glyph()
# Interactive plot using ggiraph
girafe(ggobj = fl)
This plot displays the minimum and maximum number of flights departing from each airport on a spatial map. Each line segment represents the flight range for a respective airport. The length of each segment indicates the variability in flight numbers across different airports. Notably, airports like ATL and ORD generally have a higher volume of departing flights compared to others such as MCO and PHX. Additionally, all airports exhibit fluctuations throughout the year, with broader flight intervals mid-year and narrower intervals during the holiday season at year-end.
From the graph, it is evident that airports in certain regions experience more variability than others. While segment plots provide a good estimation of this variability, the geom_glyph_ribbon enhances our understanding by displaying the gap between minimum and maximum flights. Wider ribbons suggest greater fluctuation in flight operations month-to-month.
south <- us_map(include = .south_region)
west <- us_map(include = .west_region, exclude = c("AK", "HI"))
southR <- flights |>
filter(origin %in% c("ATL", "CLT", "MCO", "DFW")) |>
ggplot(aes(x_major = long, y_major = lat,
x_minor = month, ymin_minor = min_flights,
ymax_minor = max_flights)) +
geom_sf(data = south, color = "white",
fill = "antiquewhite", inherit.aes = FALSE) +
coord_sf(crs = st_crs(4326)) +
add_glyph_boxes(color = "#A6B37D") +
add_ref_lines(color = "#A6B37D") +
geom_glyph_ribbon(color = "#A6B37D", fill = "#A6B37D") +
labs(title = "South Region") +
theme_glyph()
westR <- flights |>
filter(origin %in% c("PHX", "LAS", "LAX", "SEA")) |>
ggplot(aes(x_major = long, y_major = lat,
x_minor = month, ymin_minor = min_flights,
ymax_minor = max_flights)) +
geom_sf(data = west, color = "white",
fill = "antiquewhite", inherit.aes = FALSE) +
coord_sf(crs = st_crs(4326)) +
add_glyph_boxes(color = "#CD5C08") +
add_ref_lines(color = "#CD5C08") +
geom_glyph_ribbon(color = "#CD5C08", fill = "#CD5C08") +
labs(title = "West Region") +
theme_glyph()
grid.arrange(westR, southR, ncol = 2)
geom_glyph_ribbon()
highlights the disparities in flight
volume between regions. The Western region exhibits a larger variation
in the number of flights compared to the Southern region, as evidenced
by the thicker ribbons. Interestingly, both regions show a notable
increase in discrepancies during the mid-year, which supports our
findings from the geom_glyph_segment()
.