Area-proportional 2/3-set diagrams

Area-proportional 2/3-set diagrams

A standard Venn diagram divides the plane into all possible regions of equal visual weight, regardless of how many items each region holds. An area-proportional Venn instead scales each region’s area to its size, making the picture itself a quantitative summary.

This vignette covers when to use proportional layouts, how to generate them, and the low-level helpers (solve_2set, solve_3set, circle_intersection_area) that drive them.

library(vennDiagramLab)

When to use proportional

Set count Proportional supported? Caveats
2 yes (exact) always achievable with two circles
3 yes (approximate) three-circle constraints rarely admit an exact solution; is_approximate = TRUE
4+ no use a layered Venn or an UpSet plot instead

For 4+ sets, analyze(ds, model = "proportional") raises a clear error.

A 2-set example

We construct a small toy dataset directly (no file IO):

ds_2 <- methods::new("VennDataset",
    set_names     = c("A", "B"),
    items         = list(A = paste0("g", 1:30), B = paste0("g", 21:50)),
    item_order    = paste0("g", 1:50),
    universe_size = 100L,
    source_path   = NULL,
    format        = "csv"
)

result_2 <- analyze(ds_2, model = "proportional")
result_2@model
result_2@is_approximate

is_approximate is FALSE for 2 sets — the analytical solution always matches the input cardinalities exactly.

svg_2 <- render_venn_svg(result_2)
nchar(svg_2)

A 3-set example

ds_3 <- methods::new("VennDataset",
    set_names     = c("A", "B", "C"),
    items         = list(
        A = paste0("g", 1:40),
        B = paste0("g", 21:60),
        C = paste0("g", 41:80)
    ),
    item_order    = paste0("g", 1:80),
    universe_size = 100L,
    source_path   = NULL,
    format        = "csv"
)

result_3 <- analyze(ds_3, model = "proportional")
result_3@model
result_3@is_approximate

For 3 sets, is_approximate = TRUE — the solver minimizes a residual rather than solving exactly. Inspect result_3@regions to see the actual region sizes the layout achieves.

svg_3 <- render_venn_svg(result_3)
nchar(svg_3)

Low-level helpers

If you only need the geometry (no SVG output), use the solvers directly.

circle_intersection_area(r1, r2, d)

The lens-shaped intersection area of two circles with radii r1, r2 and center distance d.

circle_intersection_area(r1 = 1, r2 = 1, d = 1)         # ≈ 1.228
circle_intersection_area(r1 = 1, r2 = 1, d = 0)         # 1 circle inside the other -> pi*r^2
circle_intersection_area(r1 = 1, r2 = 1, d = 2)         # touching at one point -> 0

solve_2set(a_only, b_only, ab)

Returns r1, r2, d (radii + center distance) for an exact 2-set proportional layout.

geom_2 <- solve_2set(a_only = 20, b_only = 20, ab = 10)
geom_2

solve_3set(regions)

Returns approximate radii and center positions for a 3-set proportional layout. Input is a named list keyed by bitmask (1..7), where the keys represent exclusive regions: 1=A only, 2=B only, 3=AB, 4=C only, 5=AC, 6=BC, 7=ABC.

geom_3 <- solve_3set(list("1" = 20L, "2" = 20L, "4" = 20L,
                           "3" = 5L,  "5" = 5L,  "6" = 5L, "7" = 2L))
str(geom_3)

What’s next