{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualizing Data with `PerspectiveWidget`\n", "\n", "`PerspectiveWidget` offers a powerful widget that allows you to display, query, transform, and visualize your data interactively within a Jupyter Notebook. Both technical and non-technical users can use `PerspectiveWidget` to interact with datasets with a minimal amount of code, while developers can take advantage of the simple and powerful API to create their own notebooks and Voila applications using `PerspectiveWidget`.\n", "\n", "For an overview of Perspective's core concepts such as the Table, View, Schema, etc., see `table_tutorial.ipynb` in the [`jupyter-notebooks`](https://github.com/finos/perspective/tree/master/examples/jupyter-notebooks) example folder." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from perspective import Table, PerspectiveWidget\n", "from datetime import date, datetime\n", "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Creating a `PerspectiveWidget`\n", "\n", "To create a widget instance, simply call the PerspectiveWidget constructor with your dataset:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Use superstore.arrow as our example dataset\n", "import requests\n", "\n", "# Download the arrow\n", "url = \"https://unpkg.com/@jpmorganchase/perspective-examples@0.2.0-beta.2/build/superstore.arrow\"\n", "req = requests.get(url)\n", "arrow = req.content" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create a table\n", "table = Table(arrow)\n", "view = table.view()\n", "df = view.to_df()\n", "display(df.shape, df.dtypes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once the widget is created, you can interact with it like any other ``, using drag-and-drop controls to apply pivots, filters, sorts, etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create a widget, which will default to showing a datagrid\n", "widget = PerspectiveWidget(df)\n", "widget" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For more control over your dataset (if you need to update the data frequently, etc.), create a `perspective.Table` and pass its handle into the `PerspectiveWidget` container:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create a table so we can index the dataset\n", "table = Table(df, index=\"Row ID\")\n", "widget2 = PerspectiveWidget(table)\n", "widget2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When the `table` instance is updated with new data, the widget will reflect the new data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Widget will display new data when this cell is called\n", "table.update({\n", " \"Row ID\": [1],\n", " \"Order ID\": [\"new order!\"]\n", "})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Configuring `PerspectiveWidget`\n", "\n", "`PerspectiveWidget`'s initializer can be configured with the following options to control its output:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Apply pivots and aggregates, and specify columns to show\n", "PerspectiveWidget(df, columns=[\"Sales\", \"Category\"], group_by=[\"State\", \"City\"], split_by=[\"Segment\"], aggregates={\"Category\": \"dominant\"})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Sorts and filters\n", "PerspectiveWidget(df, columns=[\"Order Date\", \"State\", \"Sales\", \"Profit\"], sort=[[\"Order Date\", \"desc\"]], filter=[[\"State\", \"==\", \"Texas\"]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Calculate expression columns\n", "PerspectiveWidget(df, columns=[\"expression\"], expressions={ 'expression': '// expression\\n\"Sales\" * \"Profit\" * (sqrt(144))' })" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Show a chart by default\n", "PerspectiveWidget(df, plugin=\"Y Bar\", columns=[\"expression\"], group_by=[\"State\"], expressions={ 'expression': '//expression\\n\"Sales\" / \"Profit\"' }, sort=[[\"expression\", \"desc\"]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`save()` and `restore()` can be called to serialize a `PerspectiveWidget`'s entire state, and restore that state later on:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create a complex widget\n", "w = PerspectiveWidget(\n", " df,\n", " plugin=\"Heatmap\",\n", " columns=[\"Sales\"],\n", " group_by=[\"State\"],\n", " sort=[[\"Sales\", \"desc\"]]\n", ")\n", "\n", "config = w.save()\n", "\n", "# Restore the config\n", "PerspectiveWidget(df, **config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using `PerspectiveWidget` with `ipywidgets`\n", "\n", "Because `PerspectiveWidget` is itself an `ipywidget`, it can be easily included in any custom widget layouts and inside `ipywidget` elements:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ipywidgets as widgets\n", "\n", "w1 = PerspectiveWidget(df, **config)\n", "w2 = PerspectiveWidget(df, **config)\n", "\n", "w2.columns = [\"Profit\"]\n", "w2.sort = [[\"Profit\", \"desc\"]]\n", "\n", "# Create a tab widget with some PerspectiveWidgets inside\n", "tab = widgets.Tab()\n", "tab.children = [w1, w2]\n", "tab.titles = [\"Sales by State\", \"Profit by State\"]\n", "tab" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`PerspectiveWidget` also works well with Jupyterlab's built in layout system - right click on any widget and click `Create New View for Output`, and you can resize and reposition that widget to anywhere inside the Jupyterlab window.\n", "\n", "For more complex layouts that leverage the high performance and throughput of `perspective-python`, `perspective-workspace` allows the creation of powerful and complex front-end layouts, and integrates perfectly with `perspective-python` through the use of a Tornado server. For more details, see [this example](https://github.com/finos/perspective/tree/master/examples/workspace-editing-python)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 4 }