--- title: "Stacking Order" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Stacking Order} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.ext = "png", dev = "ragg_png" ) ggplot2::theme_set(ggplot2::theme_light()) ``` ## Small to Large (or Vice Versa) Let's start by setting up a simple plot to demonstrate stacking order options: ```{r setup} library(ggsankeyfier) library(ggplot2) ## Let's start with subsetting the data to make it less cluttered es_sub <- ecosystem_services |> subset(RCSES > quantile(RCSES, 0.99)) |> pivot_stages_longer(c("activity_realm", "biotic_realm", "service_section"), "RCSES", "service_section") p <- ggplot(es_sub, aes(x = stage, y = RCSES, group = node, connector = connector, edge_id = edge_id)) ``` Using `position_sankey()`, a stacking order can be specified. Let's start by demonstrating the ascending order (largest at the top): ```{r stack_order_asc, results='hide', fig.width=6, fig.height=3} pos <- position_sankey(v_space = "auto", order = "ascending") p + geom_sankeyedge(aes(fill = service_section), position = pos) + geom_sankeynode(position = pos) ``` This will plot the nodes and edges in descending stacking order (largest at the bottom): ```{r stack_order_des, results='hide', fig.width=6, fig.height=3} pos <- position_sankey(v_space = "auto", order = "descending") p + geom_sankeyedge(aes(fill = service_section), position = pos) + geom_sankeynode(position = pos) ``` ## More Order Please Even though the nodes and edges are sorted by their size in the plot above, it is still hard to read, as the coloured flow going to specific ecosystem components can end up anywhere and don't align for incoming and outgoing edges. This is where order options `ascending+` and `descending+` come in handy. Before sorting the edges by size, it will first arrange them by its aesthetics (in case of this example, the `fill` colour). Like so: ```{r stack_order_plus, results='hide', fig.width=6, fig.height=3} pos <- position_sankey(order = "descending+", v_space = "auto", align = "justify") p + geom_sankeyedge(aes(fill = service_section), position = pos) + geom_sankeynode(position = pos) ``` As you will notice, the edges with the same fill colour now line up. ## Give me the Power If all of this isn't enough, you can write your own ordering function, giving you full power over the stacking order of edges and nodes. This function should accept 1 argument: `data`. `position_sankey()` will call this function with a `data.frame` containing either information about nodes, or edges. Your custom function should return the same `data.frame`, with extra information for the ordering. In case of nodes, the function should add a column named `node_order`, in case of edges, two columns need to be added: `edge_order` for outgoing flows, and `edge_order_end` for incoming flows. The example below shows how you can write such a function and how it affects your plot. ```{r stack_order_custom, results='hide', fig.width=6, fig.height=3} ## Definition of a custom ordering function: custom_order <- function(data) { if ("edge_id" %in% names(data)) { # data contains edge info ## Order incoming edges from big to small data$edge_order_end <- data$y ## Order outgoing edges from small to big (note minus sign) data$edge_order <- -data$y } else { ## data contains node info data$node_order <- data$y } return(data) } pos <- position_sankey(v_space = "auto", order = custom_order) p + geom_sankeyedge(aes(fill = service_section), position = pos) + geom_sankeynode(position = pos) ```