Skip to contents

Ported byte-for-byte from the web tool's `oneVsRestEnrichment` (`packages/core/src/statistics.ts`) / Python's `one_vs_rest_enrichment` (`venn_diagram_lab.statistics`). For each set S, "rest" is the union of the inclusive members of all *other* sets, derived purely from region counts:

Usage

one_vs_rest_enrichment(
  set_names,
  inclusive_sizes,
  exclusive_only_sizes,
  union_size,
  universe_size
)

Arguments

set_names

Ordered character vector of set identifiers.

inclusive_sizes

Named integer vector: set name -> inclusive size (K).

exclusive_only_sizes

Named integer vector: set name -> items present in exactly that set alone (the single-set region's exclusive count, excl_S). Names missing from this vector default to 0.

union_size

U: union of ALL sets (sum of exclusive counts over every non-empty region, including multi-set regions).

universe_size

N: the hypergeometric sampling universe (same value [compute_pairwise()] receives as `universe_size`).

Value

A data.frame with columns `name, size, rest_size, intersection, expected, fold_enrichment, p_value, p_adjusted, p_bonferroni, significant`, sorted by `p_value` ascending.

Details

* `U` (`union_size`) = union of ALL sets = sum of the exclusive counts over every one of the `2^n - 1` region labels (items in >= 1 set). Binary mode: `U` <= the dataset's row-count universe (rows may belong to no set). Aggregated mode: `U` == universe. * `K` = `inclusive_sizes[[name]]` (inclusive size of S) * `excl_S` = `exclusive_only_sizes[[name]]` (items only in S), 0 if absent * `rest_size` = `U - excl_S` (items in >= 1 non-S set) * `k` = `K - excl_S` (S items also in >= 1 other set) * `N` (`universe_size`) = sampling universe for the hypergeometric test

**Critical:** `rest_size` is derived from `union_size` (U), NOT from `universe_size` (N). This is what makes the test meaningful: in binary mode N > U, so the observed `k` sits above the hypergeometric support minimum and the p-value is informative. When N == U (aggregated mode, universe equals union) the p-value is ~1 – mathematically honest ("no background to enrich against"), not a bug. See `.superpowers/sdd/task-F6-ts-report.md` for the full derivation.

Uses the same hypergeometric machinery as [compute_pairwise()]. Benjamini-Hochberg FDR is computed over the `n` one-vs-rest tests (one per set); Bonferroni = `min(1, p * n)`. Returned rows are sorted by p-value ascending (stable), matching the pairwise convention.

Examples

one_vs_rest_enrichment(
    set_names = c("A", "B"),
    inclusive_sizes = c(A = 10L, B = 8L),
    exclusive_only_sizes = c(A = 5L, B = 3L),
    union_size = 13L,
    universe_size = 100L
)
#>   name size rest_size intersection expected fold_enrichment      p_value
#> 1    A   10         8            5      0.8            6.25 0.0001636692
#> 2    B    8        10            5      0.8            6.25 0.0001636692
#>     p_adjusted p_bonferroni significant
#> 1 0.0001636692 0.0003273384        TRUE
#> 2 0.0001636692 0.0003273384        TRUE