I am building an alluvial plot to show if categories of species Red Listining are present or not in legislations. Some groups like "Lampreys" and "Dragonflies and damselflies" are short compared to other groups and I wanted to move the labels out connecting them to the graph with an arrow each.
I have attempted using ggrepel, although my script and output returns below graph
The code I built to create it the following:
library(ggalluvial)
library(ggplot2)
library(ggrepel)
set.seed(123)
nome_lista_levels <- c("Bees and other hymenopterans", "Dragonflies and damsleflies", "Lampreys", "Other insects", "Mammals",
"Reptiles", "Amphibians", "Boned fish", "Sharks")
status_ita_levels <- c("Threatened", "Not Threatened", "Data Deficient")
policy_levels <- c("Policy Covered", "Not Covered")
alluvial_data_test <- expand.grid(
Nome_lista = nome_lista_levels,
Status_ITA = status_ita_levels,
at.least.one.policy = policy_levels
)
alluvial_data_test$count <- sample(10:100, nrow(alluvial_data_test), replace = TRUE)
alluvial_data_test$Nome_lista <- factor(alluvial_data_test$Nome_lista, levels = nome_lista_levels)
alluvial_data_test$Status_ITA <- factor(alluvial_data_test$Status_ITA, levels = status_ita_levels)
alluvial_data_test$at.least.one.policy <- factor(alluvial_data_test$at.least.one.policy, levels = policy_levels)
non_plants <- ggplot(data = as.data.frame(alluvial_data_test),
aes(y = log(count + 1),
axis1 = Nome_lista,
axis2 = Status_ITA,
axis3 = at.least.one.policy)) +
geom_alluvium(aes(fill = Nome_lista), curve_type = "sigmoid", alpha = 0.7, size = 0.6) +
geom_stratum(aes(fill = Nome_lista), width = 0.2, fill = "white") +
geom_text_repel(
data = alluvial_data_test,
stat = "stratum",
aes(label = after_stat(stratum)),
nudge_x = 0.3, # fixed numeric nudge to right
size = 3,
segment.size = 0.2,
segment.color = "grey50",
direction = "y"
) +
geom_text(
stat = "stratum",
aes(label = after_stat(stratum)),
size = 3,
color = "black",
data = subset(as.data.frame(alluvial_data_test), !(Nome_lista %in% label_data$Nome_lista))
) +
scale_x_discrete(
limits = c("Nome_lista", "Status_ITA", "at.least.one.policy"),
expand = c(0.15, 0.05)) +
theme_void() +
theme(legend.position = "none") +
theme(text = element_text(family = "Roboto")) +
scale_fill_brewer(palette = "Set3")
What I would like is that labels of only those species groups that are much smaller than the others sit outside of the columns, while the other labels are kept in the white blocks. Overall, I would like to tidy up the labels and make them suitable for publication.
The parameter nudge_x can be passed a vector instead of a fixed number. From my test it starts from bottom left and go from there.
Edit: following your comment, could you try with this version? I added 5 0s at the end so it won’t recycle the vector. Hopefully it is what it needs. :
nudge_x = c(0.3,0,0,0,0,0,0,0.3,0.3,0,0,0,0,0,0,0,0,0,0)
You can use ggplot_build() to build the plot data table gg_pb, then gg_pb$data[[3]] will include the data used to plot the labels:
When ymax - ymin is larger than the text size the text-label will fit and we can remove the nudge_x of 0.3. So in this case only the label CITIES will be repelled.
library(ggalluvial)
library(ggplot2)
library(ggrepel)
alluvial_data <- data.frame(
Nome_lista = rep(c("Red List", "CITES", "National List", "Regional List"), each = 8),
Status_ITA = rep(c("Native", "Alien", "Naturalized", "Invasive"), times = 8),
at.least.one.policy = rep(c("Yes", "No"), times = 16),
count = c(rep(400,8), rep(.1,8), rep(800,8), rep(1800,8))
) # rep(2,8) to see that it works
non_plants <- ggplot(data = as.data.frame(alluvial_data),
aes(y = log(count + 1),
axis1 = Nome_lista,
axis2 = Status_ITA,
axis3 = at.least.one.policy)) +
geom_alluvium(aes(fill = Nome_lista), curve_type = "sigmoid", alpha = 0.7, size = 0.6) +
geom_stratum(aes(fill = Nome_lista), width = 0.2, fill = "white") +
geom_text_repel(
stat = "stratum",
aes(label = after_stat(stratum)),
nudge_x = 0.3, # fixed numeric nudge to right
size = 3,
segment.size = 0.2,
segment.color = "grey50",
direction = "y"
) +
scale_x_discrete(
limits = c("Nome_lista", "Status_ITA", "at.least.one.policy"),
expand = c(0.15, 0.05)) +
theme_void() +
theme(legend.position = "none") +
theme(text = element_text(family = "Roboto")) +
scale_fill_brewer(palette = "Set3")
gg_pb <- ggplot_build(non_plants)
gg_pb$data[[3]] <- within(gg_pb$data[[3]], x <- x - (ymax - ymin > size) * 0.3)
plot(ggplot_gtable(gg_pb))
giving

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With