##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
The vignette("plotting") workflow sorts and colours the
data frame first and hands the result to ggplot2. Development versions
of ggalluvial can instead call wompwomp from within the
alluvial layers themselves, through the sort_strata and
color_strata parameters of stat_stratum(),
stat_alluvium() and stat_flow(). The parameter
names an engine; "wompwomp" runs
sort_to_uncross(column_method = "none") for
sort_strata and get_lode_clusters() for
color_strata, the latter exposed as the computed variable
cluster. sort_strata must be given the same
value in every layer of a plot, since each layer computes its own
positions; wompwomp is still run only once per panel and the layers
share the result.
We use the same toy data as the other vignettes.
df <- data.frame(
tissue = c(
"BRAIN", "BRAIN", "BRAIN",
"STOMACH", "STOMACH", "STOMACH", "STOMACH", "STOMACH", "STOMACH",
"HEART", "HEART", "HEART", "HEART", "HEART", "HEART", "HEART",
"T CELL", "T CELL",
"B CELL", "B CELL", "B CELL", "B CELL", "B CELL", "B CELL", "B CELL", "B CELL", "B CELL"
),
cluster = c(
1, 1, 2,
1, 2, 2, 2, 2, 2,
1, 3, 3, 3, 3, 3, 3,
4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4
)
)
df |>
dplyr::group_by(tissue, cluster) |>
dplyr::summarize(value = dplyr::n()) |>
dplyr::ungroup() |>
dplyr::mutate(dplyr::across(c(tissue, cluster), as.character)) |>
print() -> clus_df_gather## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by tissue and cluster.
## ℹ Output is grouped by tissue.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(tissue, cluster))` for per-operation grouping
## (`?dplyr::dplyr_by`) instead.
## # A tibble: 8 × 3
## tissue cluster value
## <chr> <chr> <int>
## 1 B CELL 4 9
## 2 BRAIN 1 2
## 3 BRAIN 2 1
## 4 HEART 1 1
## 5 HEART 3 6
## 6 STOMACH 1 1
## 7 STOMACH 2 5
## 8 T CELL 4 2
clus_df_gather |>
ggplot(aes(y = value, axis1 = tissue, axis2 = cluster)) +
geom_alluvium(aes(fill = tissue), width = 1/12,
sort_strata = "wompwomp") +
geom_stratum(aes(fill = after_stat(cluster)), width = 1/12, color = "grey",
sort_strata = "wompwomp", color_strata = "wompwomp") +
geom_label(stat = "stratum", aes(label = after_stat(stratum)),
sort_strata = "wompwomp") +
scale_x_discrete(
limits = c("tissue", "cluster"),
expand = c(.05, .05)
)To choose an algorithm other than the default, or to tune it, pass a
list: the method selects among
sort_to_uncross()’s (or get_lode_clusters()’s)
methods, and the remaining named elements are that function’s own
arguments. Everything else wompwomp exposes lives in
sort_to_uncross_options() and
get_lode_clusters_options(), so those knobs travel in
options — passing one directly is an error that names the
constructor to use.
# arguments of sort_to_uncross() / get_lode_clusters()
geom_stratum(sort_strata = list("wompwomp", method = "tsp", alpha = 3))
geom_stratum(color_strata = list("wompwomp", method = "advanced",
resolution = 2))
# anything from the *_options() constructors goes through `options`
geom_stratum(sort_strata = list(
"wompwomp",
options = sort_to_uncross_options(weighted_metric = FALSE)
))
geom_stratum(color_strata = list(
"wompwomp", method = "left",
options = get_lode_clusters_options(cutoff = 0.3)
))Note that method = "tsp" starts the solver from a random
tour, so seed it when a plot has to be redrawn identically; the default
"neighbornet" is deterministic.
The order of the axes stays outside the layers: position
scales are trained before statistical transformations run, so a
stat_*() that permuted x would move the strata
out from under their axis labels. ggalluvial::sort_axes()
returns the recommended axis order instead, for use in
scale_x_discrete(limits = ) — exactly where the axis order
is written above.
axis_order <- ggalluvial::sort_axes(
clus_df_gather, axes = c("tissue", "cluster"), weight = "value",
engine = "wompwomp" # or list("wompwomp", method = "neighbornet")
)It runs sort_to_uncross() with
column_method set and reads off only the column order. The
strata are sorted while it searches, because candidate axis orders are
compared by the crossings they induce; that inner ordering defaults to
"neighbornet" and can be set with
strata_method. Applying the result re-sorts the strata
against the new axis order, since which strata minimise crossings
depends on which axes end up adjacent.
Sorting the axes and then the strata is two passes over a problem
sort_to_uncross(method = , column_method = ) optimises
jointly, and the column-ordering heuristic does not guarantee an
improvement — on some data it returns an order no better than the one
you started with. Check with compute_crossing_objective()
before adopting it, or call sort_to_uncross() directly and
plot the result the way vignette("plotting") does.
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 26.04.1 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] wompwomp_1.0.0 ggalluvial_0.12.6 ggplot2_4.0.3 dplyr_1.2.1
## [5] rmarkdown_2.32
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_2.0.0 compiler_4.6.1 Rcpp_1.1.2
## [5] tidyselect_1.2.1 jquerylib_0.1.4 scales_1.4.0 yaml_2.3.12
## [9] fastmap_1.2.0 R6_2.6.1 generics_0.1.4 igraph_2.3.4
## [13] knitr_1.52 MASS_7.3-66 polyclip_1.10-7 tibble_3.3.1
## [17] maketools_1.3.2 bslib_0.12.0 pillar_1.11.1 RColorBrewer_1.1-3
## [21] rlang_1.3.0 utf8_1.2.6 cachem_1.1.0 xfun_0.62
## [25] sass_0.4.10 sys_3.4.3 S7_0.2.2 otel_0.2.0
## [29] cli_3.6.6 tweenr_2.0.3 withr_3.0.3 magrittr_2.0.5
## [33] digest_0.6.39 grid_4.6.1 ggforce_0.5.0 lifecycle_1.0.5
## [37] vctrs_0.7.3 evaluate_1.0.5 glue_1.8.1 farver_2.1.2
## [41] buildtools_1.0.0 tools_4.6.1 pkgconfig_2.0.3 htmltools_0.5.9