diff --git a/doc/conf.py b/doc/conf.py index 9e789c868..e9527d3ac 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -110,6 +110,11 @@ 'developer_guide/testing': 'developer_guide', # Removal of the developer_guide folder 'developer_guide/index': 'developer_guide', + # Redirecting removed "getting started" pages to the new location + 'getting_started/explorer': 'tutorials/getting_started', + 'getting_started/hvplot': 'tutorials/getting_started', + 'getting_started/installation': 'tutorials/getting_started', + 'getting_started/interactive': 'tutorials/getting_started', } html_context.update( # noqa diff --git a/doc/getting_started/explorer.ipynb b/doc/getting_started/explorer.ipynb deleted file mode 100644 index e229d3d06..000000000 --- a/doc/getting_started/explorer.ipynb +++ /dev/null @@ -1,147 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "44877a38-b5b2-4ed4-8a59-7fe3571f03fa", - "metadata": {}, - "source": [ - "# explorer" - ] - }, - { - "cell_type": "markdown", - "id": "a8d569ea", - "metadata": {}, - "source": [ - "The *Explorer* is a [Panel](https://panel.holoviz.org)-based web application with which you can easily explore your data. While using `.hvplot()` is a convenient way to create plots from data, it assumes some *a piori* knowledge about the data itself and its structure, and also knowdlege about `.hvplot()`'s API itself. The *Explorer* is a graphical interface that offers a simple way to select and visualize the kind of plot you want to see your data with, and many options to customize that plot." - ] - }, - { - "cell_type": "markdown", - "id": "e5f15c29-1e4e-4965-88cd-b2bc844ea1a7", - "metadata": {}, - "source": [ - ":::{note}\n", - "The Explorer has been added to hvPlot in version 0.8.0 with support for Pandas objects. Support for Xarray objects has been added in version 0.9.0. Support for more data types will be added in future versions, in the meantime please report any issue or feature request on GitHub.\n", - ":::" - ] - }, - { - "cell_type": "markdown", - "id": "ddd88f96-1fe4-4990-90f6-b3ba8de51f23", - "metadata": {}, - "source": [ - "## Set up" - ] - }, - { - "cell_type": "markdown", - "id": "433023f4-5ebc-4585-9fc8-1c3f26cfd880", - "metadata": {}, - "source": [ - "Setting up the explorer is pretty simple in a notebook, you just need to make sure you have loaded the extension, either via a data type import (e.g. `import hvplot.pandas`) or directly (e.g. `hvplot.extension('bokeh')`)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8dad379b-fcbf-4f18-84ec-6c0a07187f4d", - "metadata": {}, - "outputs": [], - "source": [ - "import hvplot.pandas # noqa" - ] - }, - { - "cell_type": "markdown", - "id": "4ec628be-25e5-42d7-9ef5-6419c78b5140", - "metadata": {}, - "source": [ - "## Basic usage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f88635d-63a4-414c-a0ea-72605e0c896f", - "metadata": {}, - "outputs": [], - "source": [ - "from bokeh.sampledata.penguins import data as df\n", - "\n", - "df.head(2)" - ] - }, - { - "cell_type": "markdown", - "id": "8d638734-0a96-4d7a-8b9f-9c46403a0b3f", - "metadata": {}, - "source": [ - "The explorer is available on the `.hvplot` namespace together with the other plotting methods. It accepts most of the parameters accepted by the `.hvplot()` API. For the purpose of producing a nice example on the documentation we will instantiate an explorer with some pre-defined parameters; usually you would instantiate it without so many parameters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9c01a9f", - "metadata": {}, - "outputs": [], - "source": [ - "explorer = df.hvplot.explorer(x='bill_length_mm', y='bill_depth_mm', by=['species'])\n", - "explorer" - ] - }, - { - "cell_type": "markdown", - "id": "2fc85ce5-3c79-4e2f-8600-38d97122ffe7", - "metadata": {}, - "source": [ - "Spend some time browser the explorer and the options it offers. On this webpage it's not going to update the preview plot and code interactively, as it needs an active Python kernel, but you will get a good feeling of all you can do with it." - ] - }, - { - "cell_type": "markdown", - "id": "99aee979", - "metadata": {}, - "source": [ - "Once you are done exploring the data you may want to record the settings you have configured or save the plot. The easiest option consists of opening the *Code* tab next to *Plot* and copy/pasting the code displayed in a new notebook cell, executing it will generate exactly the same code as seen in the explorer.\n", - "\n", - "The code string is also available on the `code` attribute:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b59f550-7d99-44a0-bc96-4e7131daafcd", - "metadata": {}, - "outputs": [], - "source": [ - "eval(explorer.code)" - ] - }, - { - "cell_type": "markdown", - "id": "2a3f891b-214f-4635-84a5-bd425df7c8db", - "metadata": {}, - "source": [ - "## Conclusion" - ] - }, - { - "cell_type": "markdown", - "id": "0dbb3916", - "metadata": {}, - "source": [ - "For information on using `.hvplot.explorer()` take a look at the [User Guide](../user_guide/Explorer.ipynb)." - ] - } - ], - "metadata": { - "language_info": { - "name": "python", - "pygments_lexer": "ipython3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/getting_started/hvplot.ipynb b/doc/getting_started/hvplot.ipynb deleted file mode 100644 index 9f5522ea5..000000000 --- a/doc/getting_started/hvplot.ipynb +++ /dev/null @@ -1,432 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "158bb196-9e72-45f0-ae7d-585e66922abe", - "metadata": {}, - "source": [ - "# hvplot" - ] - }, - { - "cell_type": "markdown", - "id": "055d7cc3", - "metadata": {}, - "source": [ - "The core functionality provided by hvPlot is a **simple and high-level plotting interface** (API), modeled on [Pandas](https://pandas.pydata.org)'s `.plot` API and extended in various ways leveraging capabilities offered by the packages of the [HoloViz](https://holoviz.org) ecosystem, most notably [HoloViews](https://holoviews.org/). hvPlot can generate interactive plots with either [Bokeh](https://www.bokeh.org) (default) or [Plotly](https://plotly.com/python/), or static plots with [Matplotlib](https://matplotlib.org). hvPlot supports many data libraries of the Python ecosystem:\n", - "\n", - "* [Pandas](https://pandas.pydata.org): DataFrame, Series (columnar/tabular data)\n", - "* [XArray](https://xarray.pydata.org): Dataset, DataArray (labelled multidimensional arrays)\n", - "* [GeoPandas](https://geopandas.org): GeoDataFrame (geometry data)\n", - "* [Rapids cuDF](https://docs.rapids.ai/api/cudf/stable/): GPU DataFrame, Series (columnar/tabular data)\n", - "* [Polars](https://www.pola.rs/): DataFrame, LazyFrame, Series (columnar/tabular data)\n", - "* [Dask](https://www.dask.org): DataFrame, Series (distributed/out of core arrays and columnar data)\n", - "* [Streamz](https://streamz.readthedocs.io): DataFrame(s), Series(s) (streaming columnar data)\n", - "* [Intake](https://github.com/ContinuumIO/intake): DataSource (data catalogues)\n", - "* [Ibis](https://ibis-project.org/): DataFrame interface for many backends (DuckDB, SQLite, SnowFlake, etc.)\n", - "* [NetworkX](https://networkx.github.io/documentation/stable/): Graph (network graphs)\n" - ] - }, - { - "cell_type": "markdown", - "id": "05e0d700-a058-425c-bdce-a6e65220564a", - "metadata": {}, - "source": [ - "## Register `.hvplot`" - ] - }, - { - "cell_type": "markdown", - "id": "28f0a720-35ef-43f3-bd45-1d0facb06199", - "metadata": {}, - "source": [ - "Let's create a simple Pandas DataFrame we'll plot later." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "841fe838-888d-4bab-8d10-a7030e37b5bc", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "np.random.seed(1)\n", - "\n", - "idx = pd.date_range('1/1/2000', periods=1000)\n", - "df = pd.DataFrame(np.random.randn(1000, 4), index=idx, columns=list('ABCD')).cumsum()\n", - "df.head(2)" - ] - }, - { - "cell_type": "markdown", - "id": "e296fd3a-a4e7-40bb-a088-ff2f2b3f5346", - "metadata": {}, - "source": [ - "The most convenient way to use hvPlot is to register the `.hvplot` *accessor* on the data type you are working with. This is done with a special import of the form `import hvplot.`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e7ba9819-0fde-40b0-ba99-189d4a942fbd", - "metadata": {}, - "outputs": [], - "source": [ - "import hvplot.pandas # noqa" - ] - }, - { - "cell_type": "markdown", - "id": "368c4d14-4226-4d04-8bc8-ca47bafe7dde", - "metadata": {}, - "source": [ - "In addition to registering the `.hvplot` accessor on Pandas objects (`DataFrame` and `Series`), the import above sets the Bokeh plotting library as the default one and loads its corresponding extension.\n", - "\n", - ":::{note}\n", - "In a notebook, loading the extension means that there's actually some front-end code that is injected in the cell output of the import, this code being required for HoloViews plots to behave correctly. So make sure not to remove this cell!\n", - ":::" - ] - }, - { - "cell_type": "markdown", - "id": "09afd413", - "metadata": {}, - "source": [ - "Now simply call `.hvplot()` on the DataFrame as you would call Pandas' `.plot()`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a029c2cb", - "metadata": {}, - "outputs": [], - "source": [ - "first_plot = df.hvplot()\n", - "first_plot" - ] - }, - { - "cell_type": "markdown", - "id": "e0c0785a-43de-4f22-9dca-c5caa9c799e9", - "metadata": {}, - "source": [ - "The same process can be applied to other libraries, we'll just show another example with Xarray." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e16be263-ccb3-4ed0-b0ef-15089f8d001a", - "metadata": {}, - "outputs": [], - "source": [ - "import hvplot.xarray # noqa\n", - "import xarray as xr\n", - "\n", - "air_ds = xr.tutorial.open_dataset('air_temperature').load()\n", - "air_ds['air'].isel(time=slice(0, 1000, 60)).hvplot.image(dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "id": "341e811c-057e-4c40-b254-25d74f8f8949", - "metadata": {}, - "source": [ - "## Bokeh plots" - ] - }, - { - "cell_type": "markdown", - "id": "c59ce73e-900a-4062-9166-2a66fcdefebf", - "metadata": {}, - "source": [ - "As you can see, the default plots hvPlot generate are Bokeh plots. These plots are interactive and support panning, zooming, hovering, and clickable/selectable legends. It's worth spending some time getting used to interact with this kind of plot, try for instance zooming in on an axis and see what happens!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d261dcb7-d81f-4974-9bdc-09255736ce57", - "metadata": {}, - "outputs": [], - "source": [ - "first_plot" - ] - }, - { - "cell_type": "markdown", - "id": "73502b90-80d6-4f70-b374-e44236fb20bb", - "metadata": {}, - "source": [ - "## `hvplot` namespace" - ] - }, - { - "cell_type": "markdown", - "id": "eb68d0b3-fb9b-4844-8162-c3ec29ca194f", - "metadata": {}, - "source": [ - "The `.hvplot` namespace holds the range of supported plot methods (e.g. `line`, `scatter`, `hist`, etc.). Use tab completion to explore the available plot types.\n", - "\n", - "```python\n", - "df.hvplot.\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "26352b8f-e157-43b0-9919-cd57ffe760cb", - "metadata": {}, - "source": [ - "Similarly to Panda's API, every plot method accepts a wide range of parameters. You can explore them by calling `hvplot.help('line')` or using tab completion:\n", - "\n", - "```python\n", - "df.hvplot.line(\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "a1857839-ce65-40b6-a757-0d4eb51feacb", - "metadata": {}, - "source": [ - "## Compose plots " - ] - }, - { - "cell_type": "markdown", - "id": "c0d288f1-aca0-4448-8d9d-99aafb621a9c", - "metadata": {}, - "source": [ - "The object returned by a `.hvplot.()` call is a `HoloViews` object. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b7e6818-9bf7-4884-9b64-5eacd5564820", - "metadata": {}, - "outputs": [], - "source": [ - "plot1 = df['A'].hvplot.area(alpha=0.2, color='red', width=300)\n", - "plot2 = df['B'].hvplot.line(width=300)\n", - "print(plot2)" - ] - }, - { - "cell_type": "markdown", - "id": "2f99a75d-8c3b-462e-9500-9ab46f5ec1e3", - "metadata": {}, - "source": [ - "`HoloViews` objects can easily composed using the `+` and `*` operators:\n", - "\n", - "- ` + ` lays the plots out in a *row* container\n", - "- `( + ).cols(1)` lays the plots out in a *column* container\n", - "- ` * ` overlays the plots" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2896b706-518d-4bc9-8513-80d2cc2cbc4e", - "metadata": {}, - "outputs": [], - "source": [ - "plot1 + plot2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "813c4e2b-b6ef-425f-8742-98a8c1b983da", - "metadata": {}, - "outputs": [], - "source": [ - "plot1 * plot2" - ] - }, - { - "cell_type": "markdown", - "id": "7afab2c4-e9f2-456e-bc3b-e26c998e2236", - "metadata": {}, - "source": [ - "## Widgets-based exploration" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "347883ca-4ae1-4ec1-8429-ff66f488df64", - "metadata": {}, - "outputs": [], - "source": [ - "from bokeh.sampledata.penguins import data as df_penguins\n", - "df_penguins.head(2)" - ] - }, - { - "cell_type": "markdown", - "id": "4ec16eba-8520-43f4-b0ff-ad6680f038fc", - "metadata": {}, - "source": [ - "The `groupby` parameter allows to explore a dimension of the data using widgets." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "873280fc-9c44-4db6-a520-826d4e693218", - "metadata": {}, - "outputs": [], - "source": [ - "df_penguins.hvplot.scatter(x='bill_length_mm', y='bill_depth_mm', groupby=['island', 'sex'], dynamic=False)" - ] - }, - { - "cell_type": "markdown", - "id": "eb285877-d8fa-4b6e-81ab-79dd5bb90326", - "metadata": {}, - "source": [ - "## Display large data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "846decf2-0b4c-496e-9a1c-ebcd9eb03559", - "metadata": {}, - "outputs": [], - "source": [ - "NUM = 1_000_000\n", - "dists = [\n", - " pd.DataFrame(dict(x=np.random.normal(x, s, NUM), y=np.random.normal(y, s, NUM)))\n", - " for x, y, s in [\n", - " ( 5, 2, 0.20), \n", - " ( 2, -4, 0.10), \n", - " (-2, -3, 0.50), \n", - " (-5, 2, 1.00), \n", - " ( 0, 0, 3.00)]\n", - "]\n", - "df_large_data = pd.concat(dists, ignore_index=True)\n", - "len(df_large_data)" - ] - }, - { - "cell_type": "markdown", - "id": "e5fc9abf-0447-4b5c-a4e4-1bd830f5099e", - "metadata": {}, - "source": [ - "hvPlot provides multiple ways to display arbitrarily large datasets. The most versatile option depends on [Datashader](https://datashader.org/) (optional dependency) and simply consists of setting `rasterize` to `True`. The plot returned is an image, each pixel of that image being colorized based on the number of points it contains; which means that **all** the points contribute to the image. This plot is also dynamic, zooming in and out and panning leads to a recomputation of the image. Luckily, this all happens really fast! The plot below is generated with no less than 5 million points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "79a99e9f-8d16-4b21-8041-0966b7efc250", - "metadata": {}, - "outputs": [], - "source": [ - "df_large_data.hvplot.points('x', 'y', rasterize=True, cnorm='eq_hist', aspect=1, colorbar=False)" - ] - }, - { - "cell_type": "markdown", - "id": "5dc56ae5-a5bf-4427-8e80-bf67e28676e5", - "metadata": {}, - "source": [ - "## Geographic plots" - ] - }, - { - "cell_type": "markdown", - "id": "f759ee37-5446-4499-bbf0-37c1911f32c2", - "metadata": {}, - "source": [ - "hvPlot can generate geographic plots and handle geographic data (e.g. GeoPandas DataFrame) thank to [GeoViews](https://geoviews.org/) (optional dependency)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cde31b00-1f83-4d6d-8acf-df08ba1d42ee", - "metadata": {}, - "outputs": [], - "source": [ - "import cartopy.crs as crs\n", - "\n", - "proj = crs.Orthographic(-90, 30)\n", - "air_ds.air.sel(time='2013-06-01 12:00').hvplot.quadmesh(\n", - " 'lon', 'lat', projection=proj, project=True,\n", - " global_extent=True, cmap='viridis', coastline=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "25b389c1", - "metadata": {}, - "source": [ - "## Matplotlib or Plotly plots" - ] - }, - { - "cell_type": "markdown", - "id": "8d8ad549", - "metadata": {}, - "source": [ - "hvPlot offers the possibility to create [Matplotlib](https://matplotlib.org/) and [Plotly](https://plotly.com/) plots. Load the chosen plotting library with the `extension` function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "096532ab", - "metadata": {}, - "outputs": [], - "source": [ - "hvplot.extension('matplotlib')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f0f9846c", - "metadata": {}, - "outputs": [], - "source": [ - "air_ds.air.isel(time=slice(0, 9, 3)).hvplot.quadmesh(\n", - " 'lon', 'lat', projection=proj, project=True, global_extent=True, \n", - " cmap='viridis', rasterize=True, dynamic=False, coastline=True,\n", - " xaxis=None, yaxis=None, width=370\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "3adf5093-8797-4c9f-9125-aa916fea02aa", - "metadata": {}, - "source": [ - "## Conclusion" - ] - }, - { - "cell_type": "markdown", - "id": "cad50096", - "metadata": {}, - "source": [ - "We have briefly explored some of the main features of `.hvplot()`. There's a lot more to it! For more information on using `.hvplot()` take a look at the [Bokeh Plotting Guide](../user_guide/Plotting.ipynb) and the various plotting guides available." - ] - } - ], - "metadata": { - "language_info": { - "name": "python", - "pygments_lexer": "ipython3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/getting_started/index.md b/doc/getting_started/index.md deleted file mode 100644 index 1779d845a..000000000 --- a/doc/getting_started/index.md +++ /dev/null @@ -1,64 +0,0 @@ -# Getting Started - -Welcome to hvPlot! - -The getting started guide will get you set up with hvPlot and provide a basic overview of its features and strengths. - ---- - -::::{grid} 1 2 2 4 -:gutter: 1 1 1 2 - -:::{grid-item-card} {octicon}`plug;2.5em;sd-mr-1` Installation -:link: installation -:link-type: doc - -Install hvPlot and the dependencies required to run the guides of this site. - -+++ -[Learn more »](installation.md) -::: - -:::{grid-item-card} {octicon}`graph;2.5em;sd-mr-1` `.hvplot()` -:link: hvplot -:link-type: doc - -Discover the capabilities of `.hvplot()`, a more versatile and powerful `.plot()` API. - -+++ -[Learn more »](hvplot) -::: - -:::{grid-item-card} {octicon}`workflow;2.5em;sd-mr-1` `.interactive()` -:link: interactive -:link-type: doc - -Learn how to turn data pipelines into widget-based interactive applications with `.interactive()`. - -+++ -[Learn more »](interactive) -::: - -:::{grid-item-card} {octicon}`browser;2.5em;sd-mr-1` `.explorer()` -:link: explorer -:link-type: doc - -Start to use `.hvplot.explorer()` to explore data in a web application. - -+++ -[Learn more »](explorer) -::: - -:::: - - -```{toctree} -:titlesonly: -:hidden: -:maxdepth: 2 - -installation -hvplot -interactive -explorer -``` diff --git a/doc/getting_started/installation.md b/doc/getting_started/installation.md deleted file mode 100644 index da69f0539..000000000 --- a/doc/getting_started/installation.md +++ /dev/null @@ -1,23 +0,0 @@ -# Installation - -| | | -| --- | --- | -| Latest release | [![Github release](https://img.shields.io/github/release/holoviz/hvplot.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/hvplot/releases) [![PyPI version](https://img.shields.io/pypi/v/hvplot.svg?colorB=cc77dd)](https://pypi.python.org/pypi/hvplot) [![hvplot version](https://img.shields.io/conda/v/pyviz/hvplot.svg?colorB=4488ff&style=flat)](https://anaconda.org/pyviz/hvplot) [![conda-forge version](https://img.shields.io/conda/v/conda-forge/hvplot.svg?label=conda%7Cconda-forge&colorB=4488ff)](https://anaconda.org/conda-forge/hvplot) [![defaults version](https://img.shields.io/conda/v/anaconda/hvplot.svg?label=conda%7Cdefaults&style=flat&colorB=4488ff)](https://anaconda.org/anaconda/hvplot) | -| Python | [![Python support](https://img.shields.io/pypi/pyversions/hvplot.svg)](https://pypi.org/project/hvplot/) | - -hvPlot supports Python 3.9 and above on Linux, Windows, or Mac. hvPlot can be installed with [conda](https://conda.io/en/latest/): - - conda install hvplot - -or with `pip`: - - pip install hvplot - -Note that `hvplot` needs to run in a Jupyter environment to automatically show output plots. However, if you are using a raw Python or IPython console, it is still possible to [show the plots](https://hvplot.holoviz.org/user_guide/Viewing.html#python-command-prompt-scripts) with `hvplot.show()` or [save the plots](https://hvplot.holoviz.org/user_guide/Viewing.html#saving-plots) even if you cannot view them interactively. For versions of `jupyterlab>=3.0` the necessary extension is automatically bundled in the `pyviz_comms` package, which must be >=2.0. However note that for version of `jupyterlab<3.0` you must also manually install the JupyterLab extension with: - - conda install jupyterlab - jupyter labextension install @pyviz/jupyterlab_pyviz - -To run the guides in this site create an environment with the required dependencies: - - conda create -n hvplot-env -c conda-forge -c nodefaults hvplot geoviews datashader xarray pandas geopandas dask streamz networkx intake intake-xarray intake-parquet s3fs scipy spatialpandas pooch rasterio fiona plotly matplotlib jupyterlab diff --git a/doc/getting_started/interactive.ipynb b/doc/getting_started/interactive.ipynb deleted file mode 100644 index 178167f4c..000000000 --- a/doc/getting_started/interactive.ipynb +++ /dev/null @@ -1,193 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "c611b682-e4ec-4028-9aa6-b33c7745c494", - "metadata": {}, - "source": [ - "# interactive" - ] - }, - { - "cell_type": "markdown", - "id": "66dddf49-c70a-4ed1-98e7-76703b82fa34", - "metadata": {}, - "source": [ - "hvPlot isn't only a plotting library, it is dedicated to make data exploration easier. In this guide you will see how it can help you to get better control over your data pipelines. We define a *data pipeline* as a series of commands that *transform* some data, such as aggregating, filtering, reshaping, renaming, etc. A data pipeline may include a *load* step that will provide the input data to the pipeline, e.g. reading the data from a data base. \n", - "\n", - "When you analyze some data in a notebook that is for instance held in a Pandas DataFrame, you may find yourself having to re-run many cells after changing the parameters you provide to Pandas' methods, either to get more insights on the data or fine tune an algorithm. `.interactive()` is a solution to improve this rather cumbersome workflow, by which you replace the constant parameters in the pipeline by widgets (e.g. a number slider), that will automatically get displayed next to your pipeline output and will trigger an output update on changes. With this approach all your pipeline parameters are available in one place and you get full interactive control over the pipeline.\n", - "\n", - "`.interactive()` doesn't only work with DataFrames but also with Xarray data structures, this is what we are going to show in this guide. First we will import `hvplot.xarray` which is going make available the `.interactive()` accessor on Xarray objects." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e14aa834-59c2-4f13-af01-dcd653505350", - "metadata": {}, - "outputs": [], - "source": [ - "import hvplot.xarray # noqa\n", - "import xarray as xr" - ] - }, - { - "cell_type": "markdown", - "id": "d8f29718-cf71-4f84-b4be-3e1e3c4b8786", - "metadata": {}, - "source": [ - "We load a dataset and get a handle on its unique *air* variable." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d60b6b3a-2a1e-4094-94b2-9cc8e5ea5242", - "metadata": {}, - "outputs": [], - "source": [ - "ds = xr.tutorial.load_dataset('air_temperature')\n", - "air = ds.air\n", - "ds" - ] - }, - { - "cell_type": "markdown", - "id": "63da0ac9-3b01-4c55-8855-6436e4575aca", - "metadata": {}, - "source": [ - "We want to better understand the temporal evolution of the air temperature over different latitudes compared to a baseline. The data pipeline we build includes:\n", - "\n", - "1. filtering the data at one latitude\n", - "2. cleaning up the data\n", - "3. aggregating the temperatures by time\n", - "4. computing a rolling mean\n", - "5. subtracting a baseline from the above\n", - "\n", - "The output we choose for now is the `.describe()` method of Pandas. This pipeline has two parameters, the latitude and the temporal window of the rolling operation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5f7905ce-da82-43f2-8b27-84c5b868a588", - "metadata": {}, - "outputs": [], - "source": [ - "LATITUDE = 30.\n", - "ROLLING_WINDOW = '1D'\n", - "\n", - "baseline = air.sel(lat=LATITUDE).mean().item()\n", - "pipeline = (\n", - " air\n", - " .sel(lat=LATITUDE)\n", - " .to_dataframe()\n", - " .drop(columns='lat')\n", - " .groupby('time').mean()\n", - " .rolling(ROLLING_WINDOW).mean()\n", - " - baseline\n", - ")\n", - "pipeline.describe()" - ] - }, - { - "cell_type": "markdown", - "id": "61d07327-08ee-45c4-b5cc-c08adf50f046", - "metadata": {}, - "source": [ - "Without `.interactive()` we would manually change the values of `LATITUDE` and `ROLLING_WINDOW` to see how they affect the pipeline output. Instead we create two widgets with the values we expect them to take, we are basically declaring beforehand our parameter space. To create widgets we import [Panel](https://panel.holoviz.org) and pick two appropriate widgets from its [Reference Gallery](https://panel.holoviz.org/reference/index.html#widgets)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "81684639-5d17-43aa-90b3-2590ed951272", - "metadata": {}, - "outputs": [], - "source": [ - "import panel as pn\n", - "\n", - "w_latitude = pn.widgets.DiscreteSlider(name='Latitude', options=list(air.lat.values))\n", - "w_rolling_window = pn.widgets.RadioButtonGroup(name='Rolling window', options=['1D', '7D', '30D'])" - ] - }, - { - "cell_type": "markdown", - "id": "a49cb2c6-2e69-4a17-9ca3-ceb918460765", - "metadata": {}, - "source": [ - "Now we instantiate an *Interactive* object by calling `.interactive()` on our data. This object mirrors the underlying object API, it accepts all of its natural operations. We replace the data by the interactive object in the pipeline, and replace the constant parameters by the widgets we have just created." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "55524639-5d5d-40c1-b76f-11da152fc6bd", - "metadata": {}, - "outputs": [], - "source": [ - "airi = air.interactive()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6f63c03e-79c2-4a6c-9203-2b4727894228", - "metadata": {}, - "outputs": [], - "source": [ - "baseline = airi.sel(lat=w_latitude).mean().item()\n", - "pipeline = (\n", - " airi\n", - " .sel(lat=w_latitude)\n", - " .to_dataframe()\n", - " .drop(columns='lat')\n", - " .groupby('time').mean()\n", - " .rolling(w_rolling_window).mean()\n", - " - baseline\n", - ")\n", - "pipeline.describe()" - ] - }, - { - "cell_type": "markdown", - "id": "4bbe8553-f79c-4e46-9a58-93b7cdb3e92f", - "metadata": {}, - "source": [ - "You can see that now the pipeline when rendered doesn't only consist of its output, it also includes the widgets that control it. Change the widgets' values and observe how the output dynamically updates.\n", - "\n", - "You can notice that `.interactive()` supports the fact that the data type changed in the pipeline (see the call to `.to_dataframe`) and that it also supports math operators (`- baseline`).\n", - "\n", - "A plot would be a better output for this pipeline. We will use `.hvplot()` to create an interactive Bokeh line plot, note that using Pandas' `.plot()` is also possible." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "83e20794-0261-46f8-a094-1903937de550", - "metadata": {}, - "outputs": [], - "source": [ - "import hvplot.pandas # noqa\n", - "\n", - "pipeline.hvplot()" - ] - }, - { - "cell_type": "markdown", - "id": "c458f2a3-eeca-477f-b7c1-6b53e4d0f18c", - "metadata": {}, - "source": [ - "For information on using `.interactive()` take a look at the [User Guide](../user_guide/Interactive.ipynb)." - ] - } - ], - "metadata": { - "language_info": { - "name": "python", - "pygments_lexer": "ipython3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/index.md b/doc/index.md index 625dfc2ea..364760c41 100644 --- a/doc/index.md +++ b/doc/index.md @@ -420,7 +420,7 @@ align: center :hidden: :maxdepth: 2 -Getting Started +Tutorials User Guide Reference Gallery Topics diff --git a/doc/tutorials/getting_started.ipynb b/doc/tutorials/getting_started.ipynb new file mode 100644 index 000000000..f8e1df855 --- /dev/null +++ b/doc/tutorials/getting_started.ipynb @@ -0,0 +1,860 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "30d451ba-68b9-400f-a724-83c43caebfeb", + "metadata": { + "tags": [] + }, + "source": [ + "# Getting started\n", + "\n", + "\n", + "Welcome to hvPlot!\n", + "\n", + "This getting started guide will get you set up with hvPlot and provide a basic overview of its features and strengths.\n" + ] + }, + { + "cell_type": "markdown", + "id": "0f9962dd-4aa6-4088-b7da-0c81a91f739b", + "metadata": { + "tags": [] + }, + "source": [ + "## Installation\n", + "\n", + "\n", + "hvPlot supports Python 3.9 and above on Linux, Windows, or Mac. You can install hvPlot via the following options:\n", + "\n", + "\n", + "::::{tab-set}\n", + "\n", + ":::{tab-item} pip\n", + "```bash\n", + "pip install hvplot\n", + "```\n", + ":::\n", + "\n", + ":::{tab-item} conda\n", + "```bash\n", + "conda install conda-forge::hvplot\n", + "```\n", + ":::\n", + "\n", + ":::{tab-item} uv\n", + "```bash\n", + "uv pip install hvplot\n", + "```\n", + ":::\n", + "\n", + ":::{tab-item} other\n", + "[Installing for development](../developer_guide.md)\n", + "\n", + "`Other links`\n", + "\n", + ":::\n", + "\n", + "::::" + ] + }, + { + "cell_type": "markdown", + "id": "03f88ad3-7112-4a91-b350-64650988e234", + "metadata": { + "tags": [] + }, + "source": [ + "To run the guides in this site locally, create an environment with the required dependencies:\n", + "\n", + "```bash\n", + "conda create -n hvplot-env -c conda-forge -c nodefaults hvplot geoviews datashader xarray pandas geopandas dask streamz networkx intake intake-xarray intake-parquet s3fs scipy spatialpandas pooch rasterio fiona plotly matplotlib jupyterlab\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "3554be44-81cc-4942-85ce-166119b41517", + "metadata": { + "tags": [] + }, + "source": [ + "## Overview\n", + "\n", + "The core functionality provided by hvPlot is a **simple and high-level plotting interface** (API), modeled on [Pandas](https://pandas.pydata.org)'s `.plot` API and extended in various ways leveraging capabilities offered by the packages of the [HoloViz](https://holoviz.org) ecosystem, most notably [HoloViews](https://holoviews.org/). hvPlot can generate interactive plots with either [Bokeh](https://www.bokeh.org) (default) or [Plotly](https://plotly.com/python/), or static plots with [Matplotlib](https://matplotlib.org). hvPlot supports many data libraries of the Python ecosystem such as `pandas`, `xarray`, `dask` etc." + ] + }, + { + "cell_type": "markdown", + "id": "1fb9229d-dfce-4d91-99bc-529ce999244d", + "metadata": {}, + "source": [ + "```{image} ../assets/diagram.svg\n", + "---\n", + "alt: hvPlot diagram\n", + "align: center\n", + "width: 80%\n", + "---\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "eee1d197-112f-4012-9451-b1685a542798", + "metadata": { + "tags": [] + }, + "source": [ + "## Register `.hvplot`\n", + "\n", + "Let’s create a simple Pandas DataFrame we’ll plot later." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9a31e0c-c7e5-40a8-86f1-e14d2a12d17c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bd84ab5-2054-4ec6-ae6c-74037c7744c7", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "np.random.seed(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18ba0419-86e3-479d-9224-5d3ce7bbdb35", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "idx = pd.date_range('1/1/2000', periods=1000)\n", + "df = pd.DataFrame(np.random.randn(1000, 4), index=idx, columns=list('ABCD')).cumsum()\n", + "df.head(2)" + ] + }, + { + "cell_type": "markdown", + "id": "95adfc83-7b39-463b-80a8-bcd801563146", + "metadata": { + "tags": [] + }, + "source": [ + "The most convenient way to use hvPlot is to register the `.hvplot` *accessor* on the data type you are working with. This is done with a special import of the form `import hvplot.`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebaff587-72d8-48be-8c77-47e7f40c37d6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import hvplot.pandas # noqa" + ] + }, + { + "cell_type": "markdown", + "id": "1788969d-0b81-4cf0-b53a-594cc3f0aa63", + "metadata": {}, + "source": [ + "In addition to registering the `.hvplot` accessor on Pandas objects, the import above sets the Bokeh plotting library as the default one and loads its corresponding extension.\n", + "\n", + ":::{attention}\n", + "In a notebook, loading the extension means that there's actually some front-end code that is injected in the cell output of the import, this code being required for HoloViews plots to behave correctly. So make sure not to remove this cell!\n", + ":::\n", + "\n", + "Now simply call `.hvplot()` on the DataFrame as you would call Pandas' `.plot()`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc71994c-52ec-46d1-a220-c6ad6c1ecb21", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "first_plot = df.hvplot()\n", + "first_plot" + ] + }, + { + "cell_type": "markdown", + "id": "e587cdf0-28d0-498d-bd75-4feabd9eb262", + "metadata": {}, + "source": [ + "The same process can be applied to other libraries, we'll just show another example with Xarray." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d7c6377-33dd-44a2-9dc4-8670107ef0fb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import hvplot.xarray # noqa\n", + "import hvsampledata\n", + "\n", + "air_ds = hvsampledata.air_temperature(\"xarray\")\n", + "air_ds.hvplot.image(dynamic=False, height=300, width=400)" + ] + }, + { + "cell_type": "markdown", + "id": "0e6c5704-7fe8-4857-bcde-572279bfa819", + "metadata": { + "tags": [] + }, + "source": [ + "The default plots hvPlot generate are Bokeh plots. These plots are interactive and support panning, zooming, hovering, and clickable/selectable legends. It's worth spending some time getting used to interact with this kind of plot, try for instance zooming in on an axis and see what happens!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88da0ab4-bf41-4961-8048-bb902e04bd80", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "first_plot" + ] + }, + { + "cell_type": "markdown", + "id": "740bc606-0e4c-49f5-9c88-8ed8a09446c9", + "metadata": { + "tags": [] + }, + "source": [ + "## hvplot namespace\n", + "\n", + "The `.hvplot` namespace holds the range of supported plot methods (e.g. `line`, `scatter`, `hist`, etc.). Use tab completion to explore the available plot types.\n", + "\n", + "```python\n", + "df.hvplot.\n", + "```\n", + "\n", + "Similarly to Panda's API, every plot method accepts a wide range of parameters. You can explore them by calling `hvplot.help('line')` or using tab completion:\n", + "\n", + "```python\n", + "df.hvplot.line(\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "bfd800f5-fc0a-4404-a749-4e2b58f62bb1", + "metadata": { + "tags": [] + }, + "source": [ + "## Compose plots\n", + "\n", + "The object returned by a `.hvplot.()` call is a [HoloViews](https://holoviews.org/index.html) object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b4e0d40-0ae9-41d6-94c0-90309bb04d13", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plot1 = df['A'].hvplot.area(alpha=0.2, color='red', height=300, responsive=True)\n", + "plot2 = df['B'].hvplot.line(height=300, responsive=True)\n", + "print(plot2)" + ] + }, + { + "cell_type": "markdown", + "id": "88d3608a-79a6-4741-a24b-4703e0f8723f", + "metadata": { + "tags": [] + }, + "source": [ + "`HoloViews` objects can be easily composed using the `+` and `*` operators:\n", + "\n", + "- ` + ` lays the plots out in a *row* container\n", + "- `( + ).cols(1)` lays the plots out in a *column* container\n", + "- ` * ` overlays the plots" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4ff9c02-536b-4c4b-98a8-b24e9855d5ad", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plot1 + plot2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac816ded-94c9-44e8-84d9-8c24e1c49039", + "metadata": {}, + "outputs": [], + "source": [ + "(plot1 + plot2).cols(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd119e66-adb2-473d-8867-ce61ee1ec351", + "metadata": {}, + "outputs": [], + "source": [ + "plot1 * plot2" + ] + }, + { + "cell_type": "markdown", + "id": "75cfb3cb-db2c-4467-8b6a-d1218b3fb035", + "metadata": { + "tags": [] + }, + "source": [ + "## Widgets-based exploration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "905d2767-6e9b-43fe-86d6-a347166db07e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df_penguins = hvsampledata.penguins(\"pandas\")\n", + "df_penguins.head(2)" + ] + }, + { + "cell_type": "markdown", + "id": "c19c726c-9924-4b74-8fbe-72b6a65c5ca8", + "metadata": {}, + "source": [ + "The `groupby` parameter allows to explore a dimension of the data using widgets." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bafff17b-ccdd-40cc-ada2-3bad01e24e99", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "df_penguins.hvplot.scatter(x='bill_length_mm', y='bill_depth_mm', groupby=['island', 'sex'],\n", + " dynamic=False, height=300, width=400)" + ] + }, + { + "cell_type": "markdown", + "id": "d7ab849e-5720-4713-8c9c-158a90097f2a", + "metadata": {}, + "source": [ + "## Display large data\n", + "\n", + "hvPlot provides multiple ways to display arbitrarily large datasets. The most versatile option depends on [Datashader](https://datashader.org/) (optional dependency) and simply consists of setting `rasterize` to `True`. The plot returned is an image, each pixel of that image being colorized based on the number of points it contains; which means that all the points contribute to the image. This plot is also dynamic, zooming in and out and panning leads to a recomputation of the image. Luckily, this all happens really fast! The plot below is generated with no less than 5 million points." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a444f5ec-7bb8-476b-a12f-5f77959cb3aa", + "metadata": {}, + "outputs": [], + "source": [ + "NUM = 1_000_000\n", + "dists = [\n", + " pd.DataFrame(dict(x=np.random.normal(x, s, NUM), y=np.random.normal(y, s, NUM)))\n", + " for x, y, s in [\n", + " ( 5, 2, 0.20),\n", + " ( 2, -4, 0.10),\n", + " (-2, -3, 0.50),\n", + " (-5, 2, 1.00),\n", + " ( 0, 0, 3.00)]\n", + "]\n", + "df_large_data = pd.concat(dists, ignore_index=True)\n", + "len(df_large_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b679acc-548d-436b-a28c-986726f799a5", + "metadata": {}, + "outputs": [], + "source": [ + "df_large_data.hvplot.points('x', 'y', rasterize=True, cnorm='eq_hist',\n", + " data_aspect=1, colorbar=False)" + ] + }, + { + "cell_type": "markdown", + "id": "675984b5-b0a4-4ff2-bf4b-bc2cd51ff071", + "metadata": { + "tags": [] + }, + "source": [ + ":::{note}\n", + "This interactive functionality requires a live Python process to be running.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "3565051b-bdef-4a77-9a53-0313317c3218", + "metadata": {}, + "source": [ + "## Geographic plots\n", + "\n", + "hvPlot can generate geographic plots and handle geospatial data (e.g., GeoPandas DataFrame) on its own." + ] + }, + { + "cell_type": "markdown", + "id": "c226b5d7-8608-4998-b34a-064f7b21135c", + "metadata": {}, + "source": [ + "**Without GeoViews**\n", + "\n", + "hvPlot allows us to add a tile map as a basemap to a plot with the `tiles` parameter without having to install geoviews. This is possible because hvPlot projects lat/lon values to easting/northing (EPSG:4326 to EPSG:3857) coordinates without additional package dependencies if it detects that the values falls within expected lat/lon ranges, *unless the data is lazily loaded (dask / ibis), or the data is a spatialpandas object*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9055995-6227-446e-adcc-a6b98110a741", + "metadata": {}, + "outputs": [], + "source": [ + "earthquakes = hvsampledata.earthquakes(\"pandas\")\n", + "earthquakes.head(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbe807a6-72e7-4a30-bdae-3f9da91657ad", + "metadata": {}, + "outputs": [], + "source": [ + "earthquakes.hvplot.points('lon', 'lat', tiles=True, alpha=0.6)" + ] + }, + { + "cell_type": "markdown", + "id": "37b544b9-ee78-4288-8057-6fb8bb3af8c8", + "metadata": {}, + "source": [ + "**With GeoViews**\n", + "\n", + "For more advanced mapping features, you can optionally install [GeoViews](https://geoviews.org/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fd193b0-8e12-4762-be0a-146d8c570b25", + "metadata": {}, + "outputs": [], + "source": [ + "import cartopy.crs as crs\n", + "\n", + "proj = crs.Orthographic(-90, 30)\n", + "air_ds.hvplot.quadmesh(\n", + " 'lon', 'lat', projection=proj, project=True,\n", + " global_extent=True, cmap='viridis', coastline=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "b9db9429-c88d-44dd-bf2b-2a220820d487", + "metadata": {}, + "source": [ + "For more information, see the [User guide section](https://hvplot.holoviz.org/user_guide/Geographic_Data.html) on geographic plots" + ] + }, + { + "cell_type": "markdown", + "id": "c98e7228-889c-41ad-981b-174b890cab82", + "metadata": { + "tags": [] + }, + "source": [ + "## Matplotlib or Plotly plots\n", + "\n", + "hvPlot offers the possibility to create [Matplotlib](https://matplotlib.org/) and [Plotly](https://plotly.com/) plots. Load the chosen plotting library with the `extension` function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c7970bc-66a2-445b-b7fe-7c88ce90141b", + "metadata": {}, + "outputs": [], + "source": [ + "hvplot.extension('matplotlib')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be6f5617-7517-4881-9db7-37a9085f7918", + "metadata": {}, + "outputs": [], + "source": [ + "df_penguins.hvplot.scatter(x='bill_length_mm', y='bill_depth_mm', by='sex')" + ] + }, + { + "cell_type": "markdown", + "id": "77b34a64-a3f8-468a-b263-0b186bff6f0b", + "metadata": {}, + "source": [ + "## Rendering and saving output\n", + "\n", + "In notebook environments like Jupyter or VS Code, objects returned by hvPlot calls are displayed automatically. For example, this documentation page is built from a Jupyter notebook.\n", + "\n", + "If you’re running code outside of a notebook (e.g., in a Python script or console), you can:\n", + "\n", + "- Display plots: Use `hvplot.show()` to render plots in a browser or interactive viewer.\n", + " \n", + "- Save plots: Use `hvplot.save(, 'this_plot.html')` to save plots to an HTML file for later viewing.\n", + "\n", + ":::{tip}\n", + "When using Bokeh as the plotting backend, you can also save plots directly using the “Save” icon in the plot’s toolbar.\n", + ":::\n", + "\n", + "For more information about viewing or saving plots, check out the user guide section on [viewing plots](https://hvplot.holoviz.org/user_guide/Viewing.html#)" + ] + }, + { + "cell_type": "markdown", + "id": "279962d9-c1f5-43ce-9fc1-0f517f562ea3", + "metadata": {}, + "source": [ + "## hvPlot explorer\n", + "\n", + "The *Explorer* is a [Panel](https://panel.holoviz.org)-based web application with which you can easily explore your data. While using `.hvplot()` is a convenient way to create plots from data, it assumes some *a piori* knowledge about the data itself and its structure, and also knowledge about `.hvplot()`'s API itself. The *Explorer* is a graphical interface that offers a simple way to select and visualize the kind of plot you want to see your data with, and many options to customize that plot." + ] + }, + { + "cell_type": "markdown", + "id": "09ad8823-ba17-443e-bccc-82826240ffa7", + "metadata": {}, + "source": [ + "### Set up\n", + "\n", + "Setting up the explorer is pretty simple in a notebook. You just need to make sure you have loaded the extension, either via a data type import (e.g. `import hvplot.pandas`) or directly (e.g. `hvplot.extension('bokeh')`)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "512e7b44-f189-4e99-a7ee-7b15b72e8987", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "hvplot.output(backend='bokeh')" + ] + }, + { + "cell_type": "markdown", + "id": "6fdb3ae1-5864-4731-9d32-57324551103a", + "metadata": {}, + "source": [ + "### Basic usage" + ] + }, + { + "cell_type": "markdown", + "id": "6bc74294-7d1b-4644-8140-3b05913c5224", + "metadata": {}, + "source": [ + "The explorer is available on the `.hvplot` namespace together with the other plotting methods. It accepts most of the parameters accepted by the `.hvplot()` API. For the purpose of producing a nice example on the documentation, we will instantiate an explorer with some pre-defined parameters; usually you would instantiate it without so many parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "980f89ff-bc1e-40a7-9a78-960d275376f5", + "metadata": {}, + "outputs": [], + "source": [ + "explorer = df_penguins.hvplot.explorer(x='bill_length_mm', y='bill_depth_mm', by=['species'])\n", + "explorer" + ] + }, + { + "cell_type": "markdown", + "id": "bdd3a303-c03f-4e2f-bfc4-d6a1c2d41ab5", + "metadata": { + "tags": [] + }, + "source": [ + "Spend some time browsing the explorer and the options it offers." + ] + }, + { + "cell_type": "markdown", + "id": "11bbbf82-12fe-4e74-89bd-6d4abd61a7dc", + "metadata": { + "tags": [] + }, + "source": [ + ":::{note}\n", + "This interactive functionality requires a live Python process to be running.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "fc774dd0-8609-4ef9-a97a-1e14439bb5e0", + "metadata": { + "tags": [] + }, + "source": [ + "Once you are done exploring the data you may want to record the settings you have configured or save the plot. The easiest option consists of opening the *Code* tab next to *Plot* and copy/pasting the code displayed in a new notebook cell, executing it will generate exactly the same code as seen in the explorer." + ] + }, + { + "cell_type": "markdown", + "id": "8dbb2796-7658-45e3-9335-f0d55f2ba084", + "metadata": { + "tags": [] + }, + "source": [ + "## hvPlot interactive\n", + "\n", + "hvPlot isn't only a plotting library, it is dedicated to making data exploration easier. The `hvplot.interactive()` API can help you to get better control over your data pipelines. We define a *data pipeline* as a series of commands that *transform* some data, such as aggregating, filtering, reshaping, renaming, etc. A data pipeline may include a *load* step that will provide the input data to the pipeline, e.g. reading the data from a database. \n", + "\n", + "When you analyze some data in a notebook that is for instance held in a Pandas DataFrame, you may find yourself having to re-run many cells after changing the parameters you provide to Pandas' methods, either to get more insights on the data or fine-tune an algorithm. `.interactive()` is a solution to improve this rather cumbersome workflow, by which you replace the constant parameters in the pipeline by widgets (e.g. a number slider), that will automatically get displayed next to your pipeline output and will trigger an output update on changes. With this approach all your pipeline parameters are available in one place and you get full interactive control over the pipeline.\n", + "\n", + "`.interactive()` doesn't only work with DataFrames but also with Xarray data structures, this is what we are going to show in this guide. First we will import `hvplot.xarray` which is going to make available the `.interactive()` accessor on Xarray objects." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f12005e-a145-4732-84b3-a0bf7c0b8cee", + "metadata": {}, + "outputs": [], + "source": [ + "import hvplot.xarray # noqa" + ] + }, + { + "cell_type": "markdown", + "id": "38bbbbd3-37e0-4bb3-beab-f5953e13a7ce", + "metadata": {}, + "source": [ + "We load a dataset and get a handle on its unique *air* variable." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22c4d88c-72e3-4e38-b479-84842ce4ebb1", + "metadata": {}, + "outputs": [], + "source": [ + "air = air_ds.air\n", + "air" + ] + }, + { + "cell_type": "markdown", + "id": "81b64fc0-660b-4bf6-b233-b7398a4d50aa", + "metadata": {}, + "source": [ + "We want to better understand the temporal evolution of the air temperature over different latitudes compared to a baseline. The data pipeline we build includes:\n", + "\n", + "1. filtering the data at one latitude\n", + "2. cleaning up the data\n", + "3. aggregating the temperatures by time\n", + "4. computing a rolling mean\n", + "5. subtracting a baseline from the above\n", + "\n", + "The output we choose for now is the `.describe()` method of Pandas. This pipeline has two parameters, the latitude and the temporal window of the rolling operation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53709c6f-876b-4489-a014-f5c0d49f515d", + "metadata": {}, + "outputs": [], + "source": [ + "LATITUDE = 30.\n", + "ROLLING_WINDOW = '1D'\n", + "\n", + "baseline = air.sel(lat=LATITUDE).mean().item()\n", + "pipeline = (\n", + " air\n", + " .sel(lat=LATITUDE)\n", + " .to_dataframe()\n", + " .drop(columns='lat')\n", + " .groupby('time').mean()\n", + " .rolling(ROLLING_WINDOW).mean()\n", + " - baseline\n", + ")\n", + "pipeline.describe()" + ] + }, + { + "cell_type": "markdown", + "id": "4c06ec25-0563-4190-812b-38bb9185de70", + "metadata": {}, + "source": [ + "Without using `.interactive()`, we would need to manually change the values of `LATITUDE` and `ROLLING_WINDOW` to observe how they affect the pipeline’s output. Instead, we can create two widgets that represent the range of values we expect these parameters to take. Essentially, this allows us to define our parameter space in advance. To create the widgets, we import [Panel](https://panel.holoviz.org) and select two appropriate widgets from its [Reference Gallery](https://panel.holoviz.org/reference/index.html#widgets)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a35b33cb-7669-4128-8e1e-c57281a0cc55", + "metadata": {}, + "outputs": [], + "source": [ + "import panel as pn\n", + "\n", + "w_latitude = pn.widgets.DiscreteSlider(name='Latitude', options=list(air.lat.values))\n", + "w_rolling_window = pn.widgets.RadioButtonGroup(name='Rolling window', options=['1D', '7D', '30D'])" + ] + }, + { + "cell_type": "markdown", + "id": "7165df5b-b307-4fd4-ac30-41b7d0ce8051", + "metadata": {}, + "source": [ + "Now we instantiate an *Interactive* object by calling `.interactive()` on our data. This object mirrors the underlying object API, accepting all of its natural operations. We replace the data by the interactive object in the pipeline, and replace the constant parameters by the widgets we have just created." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a620f0a-5cc0-45fa-bb74-7a8b82c08d4c", + "metadata": {}, + "outputs": [], + "source": [ + "airi = air.interactive()\n", + "baseline = airi.sel(lat=w_latitude).mean().item()\n", + "pipeline = (\n", + " airi\n", + " .sel(lat=w_latitude)\n", + " .to_dataframe()\n", + " .drop(columns='lat')\n", + " .groupby('time').mean()\n", + " .rolling(w_rolling_window).mean()\n", + " - baseline\n", + ")\n", + "pipeline.describe()" + ] + }, + { + "cell_type": "markdown", + "id": "c5f56064-2a13-4c72-b77d-5ad64626bbd0", + "metadata": {}, + "source": [ + "You can see that now the pipeline when rendered doesn't only consist of its output, it also includes the widgets that control it. Change the widgets' values and observe how the output dynamically updates.\n", + "\n", + ":::{note}\n", + "This interactive functionality requires a live Python process to be running.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "65d19ba2-2161-4432-82ed-b9cb6e84ea6e", + "metadata": {}, + "source": [ + "You can notice that `.interactive()` supports the fact that the data type changed in the pipeline (see the call to `.to_dataframe`) and that it also supports math operators (`- baseline`).\n", + "\n", + "A plot would be a better output for this pipeline. We will use `.hvplot()` to create an interactive Bokeh line plot." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c29a9aa-0a51-4dc6-8bf6-12dade9d15ec", + "metadata": {}, + "outputs": [], + "source": [ + "pipeline.hvplot(height=300, responsive=True)" + ] + }, + { + "cell_type": "markdown", + "id": "c3c09926-9215-4c7a-9f69-94b5a9675643", + "metadata": { + "tags": [] + }, + "source": [ + ":::{note}\n", + "This interactive functionality requires a live Python process to be running.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "a1b76cc4-81fc-4e9b-8af2-53b6ddc751eb", + "metadata": { + "tags": [] + }, + "source": [ + "For more information about the various hvPlot capabilities, take a look at the [User Guide](https://hvplot.holoviz.org/user_guide/index.html)." + ] + } + ], + "metadata": { + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/tutorials/index.md b/doc/tutorials/index.md new file mode 100644 index 000000000..1af813e0e --- /dev/null +++ b/doc/tutorials/index.md @@ -0,0 +1,38 @@ +# Tutorials + +Welcome to the Tutorials section. Here, you will find clear, step-by-step guides to help you master hvPlot and explore the full holoviz ecosystem. Whether you’re just starting out, coming from pandas or xarray, or looking to sharpen your skills, these tutorials offer practical examples and hands-on learning to explore and transform your data into compelling visualizations. + +::::{grid} 1 2 2 3 +:gutter: 1 1 1 2 + +:::{grid-item-card} {octicon}`book;2.5em;sd-mr-1 sd-animate-grow50` Getting Started +:link: getting_started +:link-type: doc + +Learn how to get started with hvPlot using this quick tutorial. +::: + +:::{grid-item-card} {octicon}`repo-template;2.5em;sd-mr-1 sd-animate-grow50` Coming From Pandas? + +Learn how hvPlot mirrors the pandas API. +::: + +:::{grid-item-card} {octicon}`repo-template;2.5em;sd-mr-1 sd-animate-grow50` hvPlot for Xarray Users + +Learn how to use hvPlot to explore your Xarray data. +::: + +:::{grid-item-card} {octicon}`link;2.5em;sd-mr-1 sd-animate-grow50` Holoviz Tutorial +:link: https://holoviz.org/tutorial/index.html + +Explore all the holoviz tools in this comprehensive tutorial. +::: +:::: + +```{toctree} +:titlesonly: +:hidden: +:maxdepth: 2 + +Getting started with hvPlot +``` diff --git a/pixi.toml b/pixi.toml index 5979c8ef9..2ea4a47da 100644 --- a/pixi.toml +++ b/pixi.toml @@ -143,6 +143,7 @@ streamz = ">=0.3.0" xarray = ">=0.18.2" xyzservices = ">=2022.9.0" geodatasets = ">=2023.12.0" +hvsampledata = "*" # =================== TESTS ===================