dash-upset
Interactive UpSet plots for Plotly Dash.
Status: early development (pre-1.0). The data model, the figure factory (
create_upset), and the interactiveUpSetDash component with click-selection callback properties are implemented and tested; see the roadmap for what's next. Not yet published to PyPI or conda-forge. Documentation: https://phylatech.github.io/dash-upset/
What is an UpSet plot?
An UpSet plot visualizes the intersections of many sets. Venn and Euler diagrams become unreadable past three or four sets; UpSet replaces the overlapping circles with:
- a matrix whose columns are sets and whose rows are intersections (filled, connected dots show which sets participate in each intersection),
- set-size bars giving the cardinality of each individual set, and
- intersection-size bars giving the size of each intersection.
This scales to dozens of sets and makes the large intersections obvious at a
glance. dash-upset aims to bring this to Dash as a reusable, themeable,
callback-friendly component.
Why this exists
There is no first-class UpSet component for Dash, and wrapping the existing JavaScript implementations has real costs: UpSet.js is AGPLv3 (unsuitable for a permissively licensed library), and while UpSet 2.0 is BSD-3-Clause, embedding its React stack would drag a heavy dependency tree into every app and give up notebook rendering and static export.
dash-upset therefore keeps all UpSet logic (data model, modes, sorting,
filtering, deviation, theming) in pure Python, composing the figure from
Plotly primitives: MIT-clean and notebook-friendly. The UpSet component adds
a thin compiled React layer (react-plotly.js) on top of that same figure so
clicks surface as ordinary Dash component properties; the build artifacts are
committed, so installing and using the package needs no Node toolchain.
upset2-react remains the documented fallback engine if Plotly's interaction
ceiling is ever reached. See the roadmap for the full analysis
and the decision record.
Installation
dash-upset is not published yet. Once released:
# conda-forge (preferred)
conda install -c conda-forge dash-upset
# or pip
pip install dash-upset
Quick start
Drop the UpSet component into a Dash layout with a dataframe of boolean
indicator columns (one per set). Clicks surface as component properties your
callbacks read the standard Dash way:
import pandas as pd
from dash import Dash, Input, Output, callback, html
from dash_upset import UpSet
# One row per misclassified test example; 1 = that model got it wrong.
# Overlaps are the shared hard cases; singletons are each model's blind spots.
df = pd.DataFrame(
{
"ResNet": [1, 1, 0, 1, 0, 1],
"ViT": [1, 1, 1, 0, 0, 1],
"XGBoost": [0, 1, 1, 1, 1, 0],
}
)
app = Dash(__name__)
app.layout = html.Div(
[
UpSet(id="errors", data=df, sets=["ResNet", "ViT", "XGBoost"]),
html.Pre(id="out"),
]
)
@callback(Output("out", "children"), Input("errors", "selected_intersection"))
def show(selection):
# {"label": "ResNet & ViT", "sets": ["ResNet", "ViT"], "size": 2}
return str(selection)
if __name__ == "__main__":
app.run(debug=True)
selected_intersection updates when an intersection-size bar or a matrix dot
is clicked; selected_sets (a list of set names) updates when a set-size bar
is clicked.
Just the figure
For notebooks, scripts, or static export, create_upset takes the same input
and returns a plain plotly.graph_objects.Figure:
from dash_upset import create_upset, from_counts
fig = create_upset(
from_counts({
"Action": 320, "Comedy": 290, "Drama": 410,
"Action&Comedy": 84, "Action&Drama": 120, "Comedy&Drama": 96,
"Action&Comedy&Drama": 40,
}),
title="Movie genres",
)
fig.show()
Element-level data uses the familiar
upsetplot conventions:
from dash_upset import from_contents, from_indicators, from_memberships
from_memberships([("A",), ("A", "B"), ()]) # per-element set names
from_contents({"A": ["x", "y"], "B": ["y", "z"]}) # per-set element ids
from_indicators(boolean_dataframe) # rows = elements, columns = sets
from_indicators is dataframe-agnostic via
narwhals: pandas, Polars, PyArrow,
cuDF, and Modin frames (or a plain dict of boolean columns) all work, and
dash-upset itself depends on none of those libraries.
Sorting and display are controlled per plot, e.g.
UpSet(data=df, sets=[...], sort_by="degree", sort_sets_by="name", theme="dark");
create_upset accepts the same keywords. The full argument reference lives at
https://phylatech.github.io/dash-upset/reference.html.
Development
This project uses pixi for environment and task management.
pixi install # create the environment (deps from conda-forge)
pixi run test # run the test suite
pixi run lint # ruff lint
pixi run format # ruff format
The compiled React layer behind the UpSet component
(dash_upset_component/) is committed, so none of the above needs Node. To
change it, edit src/lib/components/DashUpset.react.js and rebuild:
npm install
pixi run build-component # webpack bundle + dash-generate-components classes
See CONTRIBUTING.md for the commit conventions that drive releases.
Prior art and credits
- UpSet and the original research by Lex, Gehlenborg, et al. define the technique.
- UpSet 2.0 by the Visualization Design Lab (BSD-3-Clause) is the technique authors' interactive reimplementation and the documented candidate engine should this library ever add a JavaScript renderer (see the roadmap).
- UpSet.js by Samuel Gratzl is an interactive JS implementation (AGPLv3 / commercial).
upsetplotby Joel Nothman (BSD-3-Clause) is the established matplotlib-based Python package;dash-upsetmirrors its familiar data-input conventions.
License
MIT © Evan Roy Rees
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dash_upset-0.1.0.tar.gz.
File metadata
- Download URL: dash_upset-0.1.0.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b8a65e8c15ec10f72626047c12826829c283b0ce4f392ded1eb08bacba72252
|
|
| MD5 |
8eee4e86bf12cd7942564154393ed543
|
|
| BLAKE2b-256 |
ef70a8e3ca6371fdbcebcbe82f85c3751eee130b1d380ba6036e6edb16dabff6
|
Provenance
The following attestation bundles were made for dash_upset-0.1.0.tar.gz:
Publisher:
release-please.yml on PhylaTech/dash-upset
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dash_upset-0.1.0.tar.gz -
Subject digest:
2b8a65e8c15ec10f72626047c12826829c283b0ce4f392ded1eb08bacba72252 - Sigstore transparency entry: 2219164803
- Sigstore integration time:
-
Permalink:
PhylaTech/dash-upset@2d981df88f5b53d8ac90e7e53a44e2d2e499a92e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PhylaTech
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@2d981df88f5b53d8ac90e7e53a44e2d2e499a92e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file dash_upset-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dash_upset-0.1.0-py3-none-any.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f95f783c837fc7fe7572a3b3284bbd6595ddf5075c57a0428df2e2d81a6087ad
|
|
| MD5 |
8485a293ec76718a66ff7f5cf8ec348b
|
|
| BLAKE2b-256 |
67149f73c3d35c45fa7e9d49afb802af7d25a14c1962be3c463bdc991b05e2be
|
Provenance
The following attestation bundles were made for dash_upset-0.1.0-py3-none-any.whl:
Publisher:
release-please.yml on PhylaTech/dash-upset
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dash_upset-0.1.0-py3-none-any.whl -
Subject digest:
f95f783c837fc7fe7572a3b3284bbd6595ddf5075c57a0428df2e2d81a6087ad - Sigstore transparency entry: 2219165213
- Sigstore integration time:
-
Permalink:
PhylaTech/dash-upset@2d981df88f5b53d8ac90e7e53a44e2d2e499a92e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/PhylaTech
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@2d981df88f5b53d8ac90e7e53a44e2d2e499a92e -
Trigger Event:
workflow_dispatch
-
Statement type: