Initial CRAN release
missing_value control for the stratum that missing (NA) entries of cols form, in prep_for_lodes(), sort_to_uncross_options(), get_lode_clusters_options(), compute_color_agreement() and plot_alluvial(). It defaults to "Missing", the label that was previously hard-coded, so results are unchanged -- but when a column that has missing entries already uses the label as a value (as ggalluvial's vaccinations does), the two used to be merged into one stratum silently, and this now warns. Set missing_value to a label the data do not use to keep them apart, or, in prep_for_lodes() and sort_to_uncross(), to NA to keep the entries missing: the stratum is then sorted like any other and returned as an explicit NA factor level (what forcats::fct_na_value_to_level() produces), which cannot collide with any value (ggalluvial does not draw missing strata, so use a label for the stratum to appear in a plot). get_lode_clusters() and lode_cluster_pal() accept such data: the former colors the NA level under its own missing_value name, the latter leaves it to the ggplot2 scale's na.value.plot_alluvial(): a single call that aggregates a wide categorical data frame with prep_for_lodes(), sorts it with sort_to_uncross(), colours the blocks with get_lode_clusters() + lode_cluster_pal(per_axis = TRUE), and renders the alluvial plot with ggalluvial. ggplot2, ggalluvial, ggforce and magrittr are now Imports; ggfittext and ggrastr are optional (Suggests) and only needed for in-stratum labels and rasterized flows.vignette("ggalluvial_integration"), split out of vignette("plotting"): how to call wompwomp from inside ggalluvial's own layers, through the sort_strata and color_strata parameters of stat_stratum() / stat_alluvium() / stat_flow() and ggalluvial::sort_axes() for the axis order, including how to select a method and pass sort_to_uncross_options() / get_lode_clusters_options() through options. vignette("plotting") now covers only the sort-then-plot workflow.get_lode_clusters(), and the internal column lookups behind prep_for_lodes(), sort_to_uncross() and compute_color_agreement(), now accept cols and wt as variables holding character vectors -- the way a programmatic caller such as ggalluvial's sort_strata and color_strata layer parameters must pass them. Previously these emitted tidyselect's "Using an external vector in selections was deprecated" warning. Bare column names, string literals and tidyselect helpers behave exactly as before.sort_to_uncross() and plot_alluvial() now expose the block distance matrix through two ratio parameters, alpha (default 2) and beta (default alpha), in place of the three constants weight_scalar, matrix_initialization_value and same_side_matrix_initialization_value. The NeighborNet (and TSP) cycle is invariant under rescaling of the whole matrix, so those constants only ever acted through the ratios matrix_initialization_value / weight_scalar (now alpha) and same_side_matrix_initialization_value / weight_scalar (now beta); the defaults alpha = beta = 2 reproduce the previous defaults (1e6 / 5e5). The three constants remain available as advanced overrides in sort_to_uncross_options() (and as arguments of plot_alluvial()), where matrix_initialization_value / same_side_matrix_initialization_value default to NULL and are derived as alpha * weight_scalar / beta * weight_scalar. Callers that passed weight_scalar alone to sort_to_uncross() must now pass it through options, and should set alpha to reproduce the old ratio (e.g. weight_scalar = 1 with the old default matrix_initialization_value = 1e6 is alpha = 1e6, options = list(weight_scalar = 1)).sort_to_uncross()'s default method is now "neighbornet" (was "tsp"), matching the algorithm described in the paper and the Python implementation.plot_alluvial()'s default sorting_algorithm is now "neighbornet" (was "tsp"), matching sort_to_uncross(), the paper, and the Python implementation.sort_to_uncross()'s default column_method and plot_alluvial()'s default column_sorting_algorithm are "neighbornet" (were "tsp"). Only affects data with more than two axes; pass "tsp" to keep the previous behavior.get_lode_clusters(method = "advanced") now maximizes modularity. igraph::cluster_leiden()'s own default objective is CPM, whose quality function compares edge weights directly against resolution, so the partition depended on the units the co-occurrence weights were in; resolution is now a modularity resolution and means the same thing for "leiden" and "louvain". Colourings (and the meaning of resolution) change from previous versions.method = "advanced" now adds one edge per unordered layer pair instead of one per ordered pair, so co-occurrence weights are no longer silently doubled. This matches wompywompy.compute_color_agreement(): the W_LOMP colour-agreement objective M (total weight of observations whose blocks share a colour across layers), summed over all layer pairs, or over adjacent pairs only with adjacent_only = TRUE.get_lode_clusters() now works with a wt column other than "value" (both the "advanced" and the reference-propagation methods previously hard-coded "value" and errored).sort_to_uncross_options(column_metric = "ari") now works. sort_to_uncross_options() lower-cases the value while determine_column_order() tested for "ARI", so the ARI layer-ordering metric was unreachable through the public API.method = "left"/"right"/a column name) now gets exactly one colour instead of duplicated rows.column_method = "random" in sort_to_uncross() (previously always errored).get_lode_clusters(method = "right") now propagates colours right-to-left (it was a duplicate of "left"), and no longer errors on a plain data.frame input.find_colors_advanced() no longer breaks when a stratum name contains an underscore.calculate_objective_fenwick()'s Binary Indexed Tree loop (the dominant cost of neighbornet sorting on large inputs) now runs as compiled Rcpp code instead of pure R.method = "barycenter" and method = "median" to sort_to_uncross(): classic Sugiyama-style two-layer crossing-reduction heuristics, cheaper (O(n log n) per pass) than greedy_wolf/greedy_wblf (O(n1*n2)). One-directional variants barycenter_one_sided/median_one_sided (paired with fixed_column, like greedy_wolf) are also available alongside the two-pass alternating default.sort_to_uncross() (and plot_alluvial()): method = "greedy", "barycenter" and "median" now sort any number of axes, not just two. Each runs one sweep forward across the axes and one back, reordering every axis against its neighbor, then (with more than two axes and column_method != "none") picks the axis order and sweeps again against the new neighbors.fixed_column now accepts a vector of column names or positions in cols, and works with every method. The fixed axes keep their incoming stratum order (the order method = "none" returns) and the rest are sorted around them. The sweep methods propagate order outward from the fixed axes. "neighbornet" and "tsp" nudge their distance matrix toward the fixed order, impose that order exactly on the resulting cycle, and choose the cycle's start and direction with the fixed axes in place; on synthetic clustered data the sweep methods reach fewer crossings than these when axes are fixed. fixed_column = NULL (the default) sorts every axis; plot_alluvial() no longer silently fixes its first column.method = "greedy_wolf", "greedy_wblf", "barycenter_one_sided" and "median_one_sided" are deprecated in favor of "greedy" (was "greedy_wblf") and "greedy"/"barycenter"/"median" with fixed_column (defaulting to cols[1], as before). The old names still work with a warning and give the same two-axis results, except that greedy_wolf no longer forces default_sorting = "fixed" on the fixed column: pass options = list(default_sorting = "fixed") to keep its first-appearance order.random_initializations now actually randomizes: previously it shuffled only factor levels, which the greedy sort ignored, so every initialization was identical. The first initialization starts from the incoming order and each further one from a random order of the non-fixed axes, keeping the fewest crossings. It now also applies to "barycenter" and "median"."value".