Package: RGraphSpace 1.4.4
This vignette demonstrates how to use RGraphSpace to visualize graph data within a spatial coordinate system. The example uses Brazilian aviation data, in which airports are represented as nodes and flights as directed edges.
This workflow is useful when graph elements need to be positioned according real-world coordinates, such as latitude and longitude, rather than an abstract graph layout. For visualization, RGraphSpace integrates ggplot2 and sf packages, allowing graph elements to be displayed together with geographic boundaries.
If you are not familiar with the basic structure of
GraphSpace objects, we recommend consulting the interoperability
vignette first.
This vignette uses preprocessed data, which are: flights records, active Brazilian airports and geographical boundaries of Brazil, and the Brazil’s Southeast Region. For full reproducibility, the data-loading and filtering procedures are described in the Preprocessing Aviation Data vignette. The present example uses Brazilian flight records from 2024.
All source data and code used during preprocessing are available in the Preprocessing Aviation Data GitHub repository.
After the data are loaded, an igraph object is constructed
by representing airports as vertices and flights as directed edges. The
resulting graph is then converted into a GraphSpace object.
Finally, a multilayered figure is constructed with ggplot2
(Wickham 2016) by combining several
sf objects with RGraphSpace geometric layers
(geoms).
Computational requirement:
Hardware: RAM >= 12 GB
Software: R (>=4.5) and RStudio
# Check required packages for this vignette
if(!require("ggplot2", quietly = TRUE)){install.packages("ggplot2")}
if(!require("dplyr", quietly = TRUE)){install.packages("dplyr")}
if(!require("sf", quietly = TRUE)){install.packages("sf")}
if(!require("rnaturalearth", quietly = TRUE)){install.packages("rnaturalearth")}
if(!require("igraph", quietly = TRUE)){install.packages("igraph")}
if(!require("maps", quietly = TRUE)){install.packages("maps")}
if(!require("ggpubr", quietly = TRUE)){install.packages("ggpubr")}
if(!require("ggrepel", quietly = TRUE)){install.packages("ggrepel")}
if(!require("rnaturalearthhires", quietly = TRUE)){
remotes::install_github("ropensci/rnaturalearthhires")}
if(!require("RGraphSpace", quietly = TRUE)){
remotes::install_github("sysbiolab/RGraphSpace", build_vignettes=TRUE)}
# Load packages
library("RGraphSpace")
library("ggplot2")
library("dplyr")
library("sf")
library("igraph")
library("ggrepel")
library("ggpubr")
Here, we need to load the preprocessed RData.
rdata_url <- paste0(
"https://raw.githubusercontent.com/",
"flaviogckessler/PreprocessingAviationData/",
"main/data/sf_brazilflights.RData")
rdata_file <- tempfile(fileext = ".RData")
download.file(url = rdata_url,destfile = rdata_file,
mode = "wb",quiet = TRUE)
loaded_objects <- load(rdata_file)
loaded_objects
#> [1] "active_airports" "flights_cf" "mapa_brasil"
rm(rdata_url,rdata_file,loaded_objects)
The loaded data comprise:
Active Brazilian airports in the selected year
(active_airports)
Filtered flight records (flights_cf)
The geographic boundaries of Brazil
(mapa_brasil)
Once the data have been loaded and filtered, the flight and airport datasets are fully compatible. We can therefore generate an igraph object using the flights as edges and the airports as vertices (nodes). To preserve the direction of each departure-arrival pair, the graph is directed. Moreover, the edges are weighted because we have the number of flights of each unique route.
graph_flights <- graph_from_data_frame(flights_cf,
directed = TRUE,
vertices = active_airports)
With the igraph object, we can readily convert it to a
GraphSpace object using GraphSpace() function. The
object is an S4 class, its nodes spot must contain columns named
x and y for further usage of
RGraphSpace geoms.
Although the coordinate system of an GraphSpace object is generally normalized to values between 0 and 1, here we keep the original latitude and longitude values. This is necessary because the graph coordinates must align with the sf object.
gs_flight <- GraphSpace(graph_flights)
gs_flight@nodes$x <- gs_flight@nodes$longitude
gs_flight@nodes$y <- gs_flight@nodes$latitude
g <- ggplot() +
geom_sf(data=mapa_brasil, fill="light grey", color="dark grey", size=.15, show.legend = FALSE) +
geom_edgespace(aes(colour = log10(weight)), arrow_size = 0.5,
arrow_offset = 0.01, data = gs_flight) +
scale_colour_continuous(palette = c("cyan","blue")) +
geom_nodespace(aes(fill=type),size=1.5,data = gs_flight) +
scale_fill_discrete(palette = c("#00BFC4","#F8766D")) +
labs(subtitle="Domestic flights in Brazil in 2024",colour="Log10 (n°of flights)",
y = "Latitude",x= "Longitude",fill="Type") +
theme_gspace_legend(key_fill = TRUE)+
theme_minimal()
g
The figure above uses two geoms from
RGraphSpace: (i) geom_edgespace(), and (ii)
geom_nodespace(). Colour and fill aesthetics are used for
edges and nodes mapping, respectively. Moreover, the figure followes the
ggplot2 grammar and demonstrates interoperability with the
sf package. In the next plot, additional aesthetics mappings
are used.
Next, we create a regional subset focusing on the airports from the Brazil’s Southeast Region, which includes some of the busiest airports in the country. The goal is to examine the relationship between flight frequency and the population of the city served by each airport.
rdata_url <- paste0(
"https://raw.githubusercontent.com/",
"flaviogckessler/PreprocessingAviationData/",
"main/data/sf_SoutheastFlights.RData")
rdata_file <- tempfile(fileext = ".RData")
download.file(url = rdata_url,destfile = rdata_file,
mode = "wb",quiet = TRUE)
loaded_objects <- load(rdata_file)
loaded_objects
#> [1] "se_airports" "se_flights" "se_states"
rm(rdata_url,rdata_file,loaded_objects)
The loaded data comprise:
Active airports in Brazil’s Southeast Region during the selected
year (se_airports)
Filtered flight records for Brazil’s Southeast Region
(se_flights)
The geographic boundaries of Brazil’s Southeast Region
(se_states)
graph_se_flights <- graph_from_data_frame(se_flights,
directed = TRUE,
vertices = se_airports)
gs_se_flight <- GraphSpace(graph_se_flights)
gs_se_flight@nodes$x <- gs_se_flight@nodes$longitude
gs_se_flight@nodes$y <- gs_se_flight@nodes$latitude
h <- ggplot() +
geom_sf(data=se_states, fill="light grey", color="red", size=.5, show.legend = FALSE) +
coord_sf(xlim = c(-53,-40))+
geom_edgespace(aes(colour = log10(weight),linewidth=log10(weight)), arrow_size = 0.5,
arrow_offset = 0.05, data = gs_se_flight) +
scale_colour_continuous(palette = c("cyan","blue")) +
scale_linewidth(guide='none')+
geom_nodespace(aes(fill=type,size = pop),data = gs_se_flight) +
geom_label_repel(aes(label = gs_se_flight@nodes$name,
x=gs_se_flight@nodes$x,
y=gs_se_flight@nodes$y),
box.padding = 0.35,
point.padding = 0.5,
size = 3,
segment.color = 'grey50') +
scale_size(range = c(1,10)) +
scale_fill_discrete(palette = c("#F8766D","#00BFC4")) +
inject_nodespace() +
labs(subtitle="Domestic flights in Brazil's Southeast Region in 2024",colour="Log10 (n°of flights)",
y = "Latitude",x= "Longitude",fill="Type",size="Population",linewidth=NULL) +
theme_gspace_legend(key_fill = TRUE)+
theme_minimal()
h
This plot uses colour and linewidth aesthetics for edges and fill and
size aesthetics for nodes. The utility function
inject_nodespace() transfer node-size information to the
edge layer, enabling it to become “node-aware” prior to final rendering.
Therefore, the arrows can align with node when node sizes vary.
Generation a geometry union with all Southeast region states:
single_sf <- st_union(se_states$geometry[1]) %>%
st_union(se_states$geometry[2]) %>%
st_union(se_states$geometry[3]) %>%
st_union(se_states$geometry[4])
Final figure arrangement:
g <- g + geom_sf(data=single_sf, fill="light grey", color="red",alpha=0, size=1, show.legend = FALSE)
ggarrange(g,h,
labels = c("A","B"),
font.label = list(size=22,face="bold"),
ncol = 2,nrow=1)
Saving figure:
png('Flights_RGraphSpace.png', units="in", width=12, height=6, res=300)
ggarrange(g,h,
labels = c("A","B"),
font.label = list(size=22,face="bold"),
ncol = 2,nrow=1)
dev.off()
#> png
#> 2
If you use RGraphSpace, please cite:
#> R version 4.6.1 (2026-06-24 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#>
#> Matrix products: default
#> LAPACK version 3.12.1
#>
#> locale:
#> [1] LC_COLLATE=Portuguese_Brazil.utf8 LC_CTYPE=Portuguese_Brazil.utf8
#> [3] LC_MONETARY=Portuguese_Brazil.utf8 LC_NUMERIC=C
#> [5] LC_TIME=Portuguese_Brazil.utf8
#>
#> time zone: America/Sao_Paulo
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] maps_3.4.3 ggpubr_1.0.0 ggrepel_0.9.8
#> [4] igraph_2.3.3 RGraphSpace_1.4.4 rnaturalearthhires_1.0.0.9000
#> [7] rnaturalearth_1.2.0 sf_1.1-1 dplyr_1.2.1
#> [10] airportr_0.1.3 ggplot2_4.0.3 data.table_1.18.4
#> [13] flightsbr_1.1.1
#>
#> loaded via a namespace (and not attached):
#> [1] tidyselect_1.2.1 vipor_0.4.7 farver_2.1.2 S7_0.2.2 fastmap_1.2.0
#> [6] janitor_2.2.1 digest_0.6.39 timechange_0.4.0 lifecycle_1.0.5 magrittr_2.0.5
#> [11] compiler_4.6.1 rlang_1.3.0 sass_0.4.10 tools_4.6.1 yaml_2.3.12
#> [16] knitr_1.51 ggsignif_0.6.4 labeling_0.4.3 classInt_0.4-11 curl_7.1.0
#> [21] xml2_1.6.0 RColorBrewer_1.1-3 abind_1.4-8 KernSmooth_2.23-26 withr_3.0.3
#> [26] purrr_1.2.2 grid_4.6.1 e1071_1.7-17 scales_1.4.0 cli_3.6.6
#> [31] rmarkdown_2.31 generics_0.1.4 remotes_2.5.0 otel_0.2.0 httr_1.4.8
#> [36] DBI_1.3.0 ggbeeswarm_0.7.3 cachem_1.1.0 proxy_0.4-29 stringr_1.6.0
#> [41] rvest_1.0.5 selectr_0.6-0 s2_1.1.11 ggrastr_1.0.2 vctrs_0.7.3
#> [46] Matrix_1.7-5 jsonlite_2.0.0 carData_3.0-6 car_3.1-5 rstatix_1.0.0
#> [51] Formula_1.2-5 archive_1.1.13 beeswarm_0.4.0 jquerylib_0.1.4 tidyr_1.3.2
#> [56] units_1.0-1 glue_1.8.1 cowplot_1.2.0 lubridate_1.9.5 stringi_1.8.7
#> [61] gtable_0.3.6 tibble_3.3.1 pillar_1.11.1 parzer_0.4.4 htmltools_0.5.9
#> [66] R6_2.6.1 wk_0.9.5 tidygraph_1.3.1 evaluate_1.0.5 lattice_0.22-9
#> [71] backports_1.5.1 broom_1.0.13 snakecase_0.11.1 bslib_0.11.0 class_7.3-23
#> [76] Rcpp_1.1.2 xfun_0.60 fs_2.1.0 pkgconfig_2.0.3