{
 "cells": [
  {
   "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.<data library>`."
   ]
  },
  {
   "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.<TAB>\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(<TAB>\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.<type>()` 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",
    "- `<plot1> + <plot2>` lays the plots out in a *row* container\n",
    "- `(<plot1> + <plot2>).cols(1)` lays the plots out in a *column* container\n",
    "- `<plot1> * <plot2>` 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
}
