cuxfilter Reference
cuxfilter is a GPU-accelerated cross-filtering dashboard library from the NVIDIA RAPIDS ecosystem. It enables interactive, multi-chart exploratory data analysis dashboards from Jupyter notebooks in just a few lines of Python. All filtering, groupby, and aggregation operations happen on the GPU via cuDF, with only the visualization results sent to the browser.
Overview
cuxfilter Reference
cuxfilter is a GPU-accelerated cross-filtering dashboard library from the NVIDIA RAPIDS ecosystem. It enables interactive, multi-chart exploratory data analysis dashboards from Jupyter notebooks in just a few lines of Python. All filtering, groupby, and aggregation operations happen on the GPU via cuDF, with only the visualization results sent to the browser.
Full documentation: https://docs.rapids.ai/api/cuxfilter/stable/ Version (stable): 26.02.00 Repository: https://github.com/rapidsai/cuxfilter
Table of Contents
- Installation and Setup
- Core Concepts
- DataFrame: Loading Data
- Charts
- Widgets
- Dashboard Creation
- Layouts
- Themes
- Dashboard Display and Export
- Graph Visualization
- Multi-GPU with Dask-cuDF
- Interoperability
- Performance Tips
- Common Patterns
Installation and Setup
Always use uv add (never pip install or conda install) in all install instructions, docstrings, comments, and error messages.
uv add --extra-index-url=https://pypi.nvidia.com cuxfilter-cu12 # For CUDA 12.x
cuxfilter depends on cuDF, so cudf-cu12 will be pulled in automatically.
Platform: Linux and WSL2 only (no native macOS or Windows). Requires: NVIDIA GPU with CUDA 12.x support.
Verify:
df = cudf.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
cux_df = cuxfilter.DataFrame.from_dataframe(df)
print(cux_df.data.head()) # Should print GPU dataframe
Core Concepts
cuxfilter has five main modules:
cuxfilter.DataFrame— Wraps a cuDF DataFrame for dashboard use. Entry point for creating dashboards.cuxfilter.DashBoard— The interactive dashboard object. Created from a DataFrame with charts.cuxfilter.charts— Chart factory functions (bar, scatter, line, heatmap, choropleth, graph, widgets).cuxfilter.layouts— Preset and custom layout configurations for chart arrangement.cuxfilter.themes— Visual themes for dashboards (default, dark, rapids, rapids_dark).
The workflow is always: Load data → Create charts → Build dashboard → Display.
DataFrame: Loading Data
The cuxfilter.DataFrame is the starting point. It wraps a cuDF or dask_cudf DataFrame.
From a cuDF DataFrame (most common)
cudf_df = cudf.DataFrame({
"x": [0, 1, 2, 3, 4],
"y": [10.0, 11.0, 12.0, 13.0, 14.0],
"category": ["A", "B", "A", "B", "A"]
})
cux_df = cuxfilter.DataFrame.from_dataframe(cudf_df)
From an Arrow file on disk
cux_df = cuxfilter.DataFrame.from_arrow("data/my_dataset.arrow")
From a graph (nodes + edges)
edges = cudf.DataFrame({"source": [0, 1, 2], "target": [1, 2, 3], "weight": [1.0, 2.0, 3.0]})
G = cugraph.Graph()
G.from_cudf_edgelist(edges, destination="target")
cux_df = cuxfilter.DataFrame.load_graph((G.nodes(), G.edges()))
Or directly from cuDF DataFrames:
nodes = cudf.DataFrame({"vertex": [0, 1, 2, 3], "x": [0, 1, 2, 3], "y": [4, 4, 2, 6], "attr": [0, 1, 1, 1]})
edges = cudf.DataFrame({"source": [0, 1, 2], "target": [1, 2, 3], "weight": [1.0, 2.0, 3.0]})
cux_df = cuxfilter.DataFrame.load_graph((nodes, edges))
Accessing the underlying data
cux_df.data # The cuDF DataFrame
cux_df.data["new_col"] = cux_df.data["x"] * 2 # Add columns before creating dashboard
Charts
All chart functions are accessed via cuxfilter.charts. They use the top-level shorthand — you do NOT need to import submodules like cuxfilter.charts.bokeh or cuxfilter.charts.datashader directly.
Bar Chart (Bokeh)
chart = cuxfilter.charts.bar(
x="column_name", # Required: x-axis column
y=None, # Optional: y-axis column (defaults to count)
data_points=None, # Number of bins (None = nunique)
add_interaction=True, # Enable cross-filtering interaction
aggregate_fn="count", # 'count' or 'mean'
step_size=None, # Step size for range slider
title="", # Chart title
autoscaling=True, # Auto-scale y-axis on data update
)
Line Chart (Bokeh)
chart = cuxfilter.charts.line(
x="x_col",
y="y_col",
data_points=100,
add_interaction=True,
)
Scatter Plot (Datashader — handles millions of points)
chart = cuxfilter.charts.scatter(
x="x_col",
y="y_col",
aggregate_col=None, # Column for color aggregation
aggregate_fn="count", # 'count', 'mean', 'max', 'min'
color_palette=None, # Bokeh palette or list of hex colors
point_size=15,
pixel_shade_type="eq_hist", # 'eq_hist', 'linear', 'log', 'cbrt'
pixel_density=0.5, # [0, 1], higher = denser
pixel_spread="dynspread", # 'dynspread' or 'spread'
tile_provider=None, # Map tile (e.g., "CartoLight" for geo data)
title="",
unselected_alpha=0.2, # Transparency of unselected points
)
Heatmap (Datashader)
chart = cuxfilter.charts.heatmap(
x="x_col",
y="y_col",
aggregate_col="value_col",
aggregate_fn="mean", # 'count', 'mean', 'max', 'min'
color_palette=None,
point_size=10,
point_shape="rect_vertical", # 'circle', 'square', 'rect_vertical', 'rect_horizontal'
title="",
)
Stacked Lines (Datashader)
chart = cuxfilter.charts.stacked_lines(
x="time_col",
y=["series_a", "series_b", "series_c"], # List of y columns
colors=["red", "green", "blue"],
)
Choropleth (Deck.gl — 2D and 3D maps)
chart = cuxfilter.charts.choropleth(
x="zip_code",
color_column="metric_col",
color_aggregate_fn="mean", # 'count', 'mean', 'sum', 'min', 'max', 'std'
elevation_column="value_col", # Set for 3D choropleth, omit for 2D
elevation_factor=0.00001,
elevation_aggregate_fn="sum",
geoJSONSource="https://url/to/geojson",
geo_color_palette=None, # Default: Inferno256
nan_color="#d3d3d3",
tooltip=True,
tooltip_include_cols=["zip_code", "metric_col"],
title="",
)
Graph (Datashader — node-link diagrams)
chart = cuxfilter.charts.datashader.graph(
node_x="x", # Default "x"
node_y="y", # Default "y"
node_id="vertex", # Default "vertex"
edge_source="source", # Default "source"
edge_target="target", # Default "target"
node_aggregate_col=None,
node_color_palette=None,
edge_color_palette=["#000000"],
node_point_size=15,
node_pixel_shade_type="eq_hist",
edge_render_type="direct", # 'direct' or 'curved' (curved is experimental)
edge_transparency=0, # [0, 1]
tile_provider=None,
title="",
unselected_alpha=0.2,
)
Widgets
Widgets provide interactive filtering controls, typically placed in the sidebar.
Range Slider
widget = cuxfilter.charts.range_slider("numeric_col", step_size=1)
Date Range Slider
widget = cuxfilter.charts.date_range_slider("datetime_col")
Float Slider
widget = cuxfilter.charts.float_slider("float_col", step_size=0.5)
Int Slider
widget = cuxfilter.charts.int_slider("int_col", step_size=1)
Dropdown
widget = cuxfilter.charts.drop_down("category_col")
Multi-Select
widget = cuxfilter.charts.multi_select("category_col")
Number (KPI indicator)
widget = cuxfilter.charts.number(
expression="column_name", # Or a computed expression like "(x + y) / 2"
aggregate_fn="mean", # 'count', 'mean', 'min', 'max', 'sum', 'std'
title="Average Value",
format="{value:.2f}", # Python format string
colors=[(33, "green"), (66, "gold"), (100, "red")], # Threshold coloring
font_size="18pt",
)
Card (Markdown content)
widget = cuxfilter.charts.card(pn.pane.Markdown("## My Dashboard\
Some description text"))
Dashboard Creation
Create a dashboard by calling .dashboard() on a cuxfilter DataFrame:
# Define charts and widgets
chart1 = cuxfilter.charts.scatter(x="x_col", y="y_col")
chart2 = cuxfilter.charts.bar("category_col")
sidebar_widget = cuxfilter.charts.range_slider("value_col")
number_widget = cuxfilter.charts.number(expression="value_col", aggregate_fn="mean", title="Mean Value")
# Build dashboard
d = cux_df.dashboard(
charts=[chart1, chart2], # Main area charts
sidebar=[sidebar_widget, number_widget], # Sidebar widgets
layout=cuxfilter.layouts.feature_and_base,
theme=cuxfilter.themes.rapids_dark,
title="My Dashboard",
data_size_widget=True, # Show current data count
)
Adding charts after creation
new_chart = cuxfilter.charts.line("x_col", "y_col")
d.add_charts(charts=[new_chart])
# or
d.add_charts(sidebar=[cuxfilter.charts.card(pn.pane.Markdown("# Note"))])
Layouts
Preset Layouts
| Layout | Description | Charts |
|---|---|---|
layouts.single_feature | One chart fills the page | 1 |
layouts.feature_and_base | Large chart on top, smaller below (66/33 split) | 2 |
layouts.double_feature | Two charts side-by-side | 2 |
layouts.left_feature_right_double | One large left, two stacked right | 3 |
layouts.triple_feature | Three charts in a row | 3 |
layouts.feature_and_double_base | One large top, two below | 3 |
layouts.two_by_two | 2x2 grid | 4 |
layouts.feature_and_triple_base | One large top, three below | 4 |
layouts.feature_and_quad_base | One large top, four below | 5 |
layouts.feature_and_five_edge | One large center, five around | 6 |
layouts.two_by_three | 2x3 grid | 6 |
layouts.double_feature_quad_base | Two large top, four below | 6 |
layouts.three_by_three | 3x3 grid | 9 |
Custom Layouts with layout_array
Use layout_array for full control. It's a list-of-lists where each inner list is a row, and numbers refer to chart indices (1-based):
# Chart 1 takes top-left 2x2 area, charts 2 and 3 on the right
d = cux_df.dashboard(
charts_list,
layout_array=[[1, 1, 2, 2], [1, 1, 3, 4]],
theme=cuxfilter.themes.rapids_dark,
)
Rules:
- Each number maps to a chart (1 = first chart, 2 = second, etc.)
- Repeating a number across cells makes that chart span those cells
- The array is auto-scaled to fit the screen
Themes
Four built-in themes:
| Theme | Description |
|---|---|
cuxfilter.themes.default | Light theme (default) |
cuxfilter.themes.dark | Dark theme |
cuxfilter.themes.rapids | RAPIDS-branded light theme |
cuxfilter.themes.rapids_dark | RAPIDS-branded dark theme |
d = cux_df.dashboard(charts, theme=cuxfilter.themes.rapids_dark)
Dashboard Display and Export
Display inline in a notebook
d.app(sidebar_width=280, width=1200, height=800)
Display as a separate web app (opens new browser tab)
d.show()
# or with custom URL/port
d.show(notebook_url="http://localhost:8888", port=8050)
JupyterHub deployment
d.show(service_proxy="jupyterhub")
Stop the server
d.stop()
Export filtered data
After interacting with the dashboard (selecting ranges, filtering), export the current filtered DataFrame:
filtered_df = d.export() # Returns cuDF DataFrame matching current filter state
# Also prints the query string, e.g.: "2 <= key <= 4"
Access dashboard charts
d.charts # Dictionary of chart objects
Graph Visualization
cuxfilter integrates with cuGraph for interactive graph visualization:
# Create graph
edges = cudf.DataFrame({
"source": [0, 0, 1, 1, 2],
"target": [1, 2, 2, 3, 3]
})
G = cugraph.Graph()
G.from_cudf_edgelist(edges, destination="target")
# Load into cuxfilter (needs node positions — use force_atlas2 or similar layout)
positions = cugraph.force_atlas2(G)
nodes = positions.rename(columns={"vertex": "vertex", "x": "x", "y": "y"})
cux_df = cuxfilter.DataFrame.load_graph((nodes, G.edges()))
# Create graph chart
chart = cuxfilter.charts.datashader.graph(
node_pixel_shade_type="linear",
unselected_alpha=0.2,
)
d = cux_df.dashboard([chart], layout=cuxfilter.layouts.single_feature)
d.app()
Multi-GPU with Dask-cuDF
cuxfilter works seamlessly with dask_cudf.DataFrame — just pass it in place of a cuDF DataFrame:
ddf = dask_cudf.read_parquet("large_dataset/*.parquet")
cux_df = cuxfilter.DataFrame.from_dataframe(ddf)
# Everything else is the same
chart = cuxfilter.charts.scatter(x="x", y="y")
d = cux_df.dashboard([chart])
d.app()
Use dask_cudf when:
- Data doesn't fit in a single GPU's memory
- You want to distribute across multiple GPUs
- Processing many files at once
Supported chart types with dask_cudf:
- bokeh: bar, line
- datashader: scatter, line, stacked_lines, heatmap, graph (limited edge rendering)
- panel_widgets: all widgets
- deckgl: choropleth (2D and 3D)
Interoperability
cuxfilter sits at the visualization layer of the RAPIDS ecosystem:
- cuDF — The data layer. cuxfilter.DataFrame wraps cuDF DataFrames.
- cuGraph — Graph analytics. Use
cuxfilter.DataFrame.load_graph()to visualize cuGraph results. - cuML — Run cuML, then visualize results (e.g., UMAP embeddings, cluster assignments) with cuxfilter.
- HoloViz ecosystem — Built on Panel, Bokeh, Datashader, and HoloViews.
- Deck.gl — WebGL-powered choropleth maps.
Typical RAPIDS + cuxfilter pipeline
# Load and preprocess with cuDF
df = cudf.read_parquet("data.parquet")
df = df.dropna().reset_index(drop=True)
# Run ML with cuML (e.g., UMAP for dimensionality reduction)
from cuml.manifold import UMAP
umap = UMAP(n_components=2)
embedding = umap.fit_transform(df[["feature1", "feature2", "feature3"]])
df["umap_x"] = embedding[:, 0]
df["umap_y"] = embedding[:, 1]
# Visualize with cuxfilter
cux_df = cuxfilter.DataFrame.from_dataframe(df)
scatter = cuxfilter.charts.scatter(
x="umap_x", y="umap_y",
aggregate_col="cluster_label",
aggregate_fn="mean",
pixel_shade_type="linear",
)
bar = cuxfilter.charts.bar("cluster_label")
d = cux_df.dashboard([scatter, bar], layout=cuxfilter.layouts.feature_and_base)
d.