Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Interactive pivot tables and charts in Jupyter

PerspectiveWidget puts the full <perspective-viewer> UI in a notebook cell. Pass it a DataFrame and you get a sortable, filterable data grid; drag a column to Group By and it becomes a pivot table; pick a chart type and it becomes a bar, line, scatter, heatmap, treemap or map — all without writing plotting code or re-running the cell.

pip install "perspective-python[jupyter]"
import pandas as pd
from perspective.widget import PerspectiveWidget

df = pd.read_parquet("trips.parquet")
PerspectiveWidget(df)

It is built on anywidget, so the same wheel works in JupyterLab, classic Jupyter Notebook, VS Code notebooks, Google Colab and marimo, with no separate lab extension to install or version-match.

Why use it instead of df.head() or a plotting library

  • The whole DataFrame, not a preview. The grid virtual-scrolls, so a multi-million row frame is browsable, sortable and filterable in place.
  • Exploration without code. Grouping, pivoting, aggregating, filtering and charting are drag-and-drop. Computed columns use a built-in expression language.
  • Reproducible. Every choice made in the UI is a keyword argument, so an exploration can be frozen back into the cell:
PerspectiveWidget(
    df,
    plugin="Heatmap",
    group_by=["pickup_hour"],
    split_by=["weekday"],
    columns=["fare"],
    aggregates={"fare": "avg"},
)
  • Live. Pass a perspective.Table instead of a DataFrame and call table.update() from another cell or thread; the widget ticks in real time.

pandas, polars and pyarrow

pandas.DataFrame, polars.DataFrame, pyarrow.Table, Arrow IPC bytes, CSV strings, and lists or dicts of Python values are all accepted directly; see DataFrame and Arrow compatibility.

Where the data lives

By default (binding_mode="server") the data stays in the Python kernel and the browser is streamed only the window of rows it is displaying, so very large frames open quickly. For the most fluid interaction on small and medium data, binding_mode="client-server" additionally replicates the table into the browser’s WebAssembly engine:

PerspectiveWidget(df, binding_mode="client-server")

For frames which strain the kernel’s memory, build the table with page_to_disk so its columns are memory-mapped from disk, and pass the table to the widget:

import perspective

table = perspective.table(df, page_to_disk=True)
PerspectiveWidget(table)

See PerspectiveWidget for notebooks for the full widget API.

From notebook to application

The engine and UI in the notebook are the same ones used in production web applications. A configuration explored in Jupyter can be saved as JSON and restored in a <perspective-viewer> served from Tornado, FastAPI or aiohttp.