# \[ANN\] UpSetPlot.jl

**URL:** <https://discourse.julialang.org/t/ann-upsetplot-jl/136848>\
**Category:** Package Announcements\
**Tags:** plotting\
**Created:** [April 24, 2026, 8:34am UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848 "2026-04-24T08:34:40Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ljournot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ljournot/32/37167_2.png) [@ljournot](https://discourse.julialang.org/u/ljournot)\
**Post date:** [April 24, 2026, 8:34am UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848/1 "2026-04-24T08:34:41Z")

</div>

# Announcing UpSetPlot.jl

I announce **[UpSetPlot.jl](https://github.com/ljournot/UpSetPlot.jl)**, a (minimalist) Julia package for plotting [UpSet plots](https://en.wikipedia.org/wiki/UpSet_plot), a data visualization method for showing set data with more than three intersecting sets. UpSet plots are now frequently used instead of [Venn diagrams](https://en.wikipedia.org/wiki/Venn_diagram), especially in life sciences.

## Features

- Plots UpSet plots
- Horizontal, vertical, opt. cumulative intersection size for each intersection degree.
- Produces the lists of elements specific to each set intersections.

## Installation

```julia
using Pkg
Pkg.add("UpSetPlot")

```

## Example

```julia
julia> using UpSetPlot
julia> using DataFrames
julia> set_names = ["Set1", "Set2", "Set3", "Set4", "Set5", "Set6"]
julia> df1 = DataFrame(
    Set1 = ["ID01", "ID02", "ID03", "ID07", "ID08", "ID09", "ID10", "ID04", "ID05", "ID06"],
    Set2 = ["ID01", "ID02", "ID03", "ID04", "ID05", "ID11", "ID12", "ID13", "ID14", "ID15"],
    Set3 = ["ID01", "ID02", "ID03", "ID07", "ID13", missing, missing, missing, missing, missing],
    Set4 = ["ID16", "ID17", "ID18", "ID19", "ID14", "ID02", "ID03", missing, missing, missing],
    Set5 = fill(missing, 10),
    Set6 = ["ID01", "ID02", "ID03", "ID04", "ID05", "ID11", "ID12", "ID13", "ID16", missing],
    Col_x = ["x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10"]
)
julia> df2 = DataFrame(
    id = ["ID01", "ID02", "ID03", "ID04", "ID05", "ID06", "ID07", "ID08", "ID09", "ID10", "ID11", "ID12", "ID13", "ID14", "ID15", "ID16", "ID17", "ID18", "ID19"],
    Set1 = [true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false],
    Set2 = [true, true, true, true, true, false, false, false, false, false, true, true, true, true, true, false, false, false, false],
    Set3 = [true, true, true, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, false],
    Set4 = [false, true, true, false, false, false, false, false, false, false, false, false, false, true, false, true, true, true, true],
    Set5 = fill(false, 19),
    Set6 = [true, true, true, true, true, false, false, false, false, false, true, true, true, false, false, true, false, false, false]
)
julia> fig1, lists1 = upset_plot(df1; set_names=set_names, intersection_lists=true);
julia> fig2, lists2 = upset_plot(df2; orientation=:h, cumul=true, intersection_lists=true);
julia> lists1 == lists2
true
julia> lists1["Set1"] == ["ID06", "ID08", "ID09", "ID10"]
true
julia> lists2["Set1_Set2_Set6"] == ["ID04", "ID05"]
true
julia> to_dataframe(lists1)

```

 ![Example intersection lists](https://global.discourse-cdn.com/julialang/original/3X/a/5/a5138592e9858a1ef8d7d115aa7b3b950d8489c2.png)

```julia
julia> display(fig1)

```

 ![Vertical UpSet plot](https://global.discourse-cdn.com/julialang/original/3X/a/c/ac6f946b5c059437b4d1747649dd46970077b037.png)

```julia
julia> display(fig2)

```

 ![Horizontal UpSet plot with cumulative intersection size for each intersection degree](https://global.discourse-cdn.com/julialang/original/3X/d/0/d087bae074298d457765403ca2e0159a77f30814.png)

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [April 24, 2026, 11:13am UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848/2 "2026-04-24T11:13:47Z")

</div>

That is a very nice plot, thanks for sharing! 🙂 :juliaheartpulse_dark:

First feature request would be to sort the rows/columns by intersection size. That is convenient as explained in the Wikipedia page. Maybe an option `sort=true` that is enabled by default?

Also, I would try to rename the functions to make them more idiomatic for Julia users, e.g., without underscores. `upsetplot` would be preferred. The function `to_dataframe` is also suspicious for those of us programming in Julia for a long time.

As a final suggestion, consider making this a Makie.jl recipe instead, so that people can use the recipe with any backend, including interactive ones (e.g., GLMakie.jl):

> **[Recipes | Makie](https://docs.makie.org/dev/explanations/recipes)**
>
> Create impressive data visualizations with Makie, the plotting ecosystem for the Julia language. Build aesthetic plots with beautiful customizable themes, control every last detail of publication quality vector graphics, assemble complex layouts and...

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [April 24, 2026, 2:01pm UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848/3 "2026-04-24T14:01:54Z")

</div>

> [@juliohm](#):
>
> `upsetplot` would be preferred

For the record, I would _strongly_ prefer `upset_plot`, and I don’t think it is any less idiomatic than `upsetplot`. As the [The current state of function naming style](https://discourse.julialang.org/t/the-current-state-of-function-naming-style/136849) thread shows, the `mashedcase` convention that is encouraged (but inconsistently applied) in core Julia is rather controversial across the wider Julia ecosystem, and certainly does not reflect a consensus (unlike `snake_case`)

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [April 30, 2026, 4:17pm UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848/4 "2026-04-30T16:17:48Z")

</div>

Cross-posting as it is relevant here too:

> [@The current state of function naming style](https://discourse.julialang.org/t/the-current-state-of-function-naming-style/136849/20):
>
> I usually avoid underscores in function names by designing APIs that are made of simple verbs and structs that hold complex state (and name). Instead of writing required\_action\_to\_take(args...) like in C, I take this long name as a sign that the software design can be improved. I introduce auxiliary structs to hold state ComplexMethodInCamelCase and a simple short verb (e.g., perform) to execute: method1 = ComplexMethodInCamelCase(...) method2 = AnotherComplexMethodToConsider(...) perform(arg…

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 1, 2026, 7:37am UTC](https://discourse.julialang.org/t/ann-upsetplot-jl/136848/5 "2026-05-01T07:37:56Z")

</div>

> [@goerz](#):
>
> For the record, I would _strongly_ prefer `upset_plot`

That goes against the convention in most plotting libraries though, and that is not specific to Julia:

- `heatmap` is not `heat_map`
- `scatterlines` is not `scatter_lines`
- `biplot` is not `bi_plot`
- `barplot` is not `bar_plot`
- `streamplot` is not `stream_plot`
- etc.
