{
"cells": [
{
"cell_type": "markdown",
"id": "a229bf0b-97ba-41ca-b68f-3011ca82198d",
"metadata": {},
"source": [
"# Integrations"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42ebab2c-ee59-4157-9b01-c1bb7988b407",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"np.random.seed(1)"
]
},
{
"cell_type": "markdown",
"id": "77441d7f-1221-4c95-8bc3-ed59c8a8f815",
"metadata": {},
"source": [
"## Data sources"
]
},
{
"cell_type": "markdown",
"id": "4471a77a-8fca-4af4-94f5-d4c753dc73dd",
"metadata": {},
"source": [
"The `.hvplot()` plotting API supports a wide range of data sources. Most frequently, a special import can be executed to register the `.hvplot` accessor on a data type. For instance, importing `hvplot.pandas` registers the `.hvplot` accessor on Pandas `DataFrame` and `Series` objects, allowing to call `df.hvplot.line()`.\n",
"\n",
"Among the data sources introduced below, Pandas](https://pandas.pydata.org) is the only library that doesn't need to be installed separately as it is a direct dependency of hvPlot."
]
},
{
"cell_type": "markdown",
"id": "36c62864-1974-4988-b360-ef598510a8cb",
"metadata": {},
"source": [
":::{note}\n",
"Supporting so many data sources is hard work! We are aware that the support for some of them isn't as good as we would like. If you encounter any issue please report it on GitHub, we always welcome Pull Requests too!\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "c2c17bf8-a261-4e4a-8517-919ee9968f71",
"metadata": {},
"source": [
"### Columnar/tabular"
]
},
{
"cell_type": "markdown",
"id": "3661b25b-ee68-4765-a7b0-0c322d3c3b24",
"metadata": {},
"source": [
"#### Pandas\n",
"\n",
"`.hvplot()` supports [Pandas](https://pandas.pydata.org) `DataFrame` and `Series` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7fc2101e-b4fd-45f5-b9a3-9432a79a3ace",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.pandas # noqa\n",
"import pandas as pd\n",
"\n",
"df_pandas = pd.DataFrame(np.random.randn(1000, 4), columns=list('ABCD')).cumsum()\n",
"df_pandas.head(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8043bcc0-cdf2-4596-b1bd-82152073f9b8",
"metadata": {},
"outputs": [],
"source": [
"# Pandas DataFrame\n",
"df_pandas.hvplot.line(height=150)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ad93bfdc-58ac-43aa-9ed5-0362686ffd12",
"metadata": {},
"outputs": [],
"source": [
"# Pandas Series\n",
"s_pandas = df_pandas['A']\n",
"s_pandas.hvplot.line(height=150)"
]
},
{
"cell_type": "markdown",
"id": "dde9e4ae-ba2b-4b6f-bf3b-a34c4d9d903b",
"metadata": {},
"source": [
"#### [Dask](https://www.dask.org)"
]
},
{
"cell_type": "markdown",
"id": "8fc945c3-9c79-497e-acd7-e3601e522da0",
"metadata": {},
"source": [
"`.hvplot()` supports [Dask](https://www.dask.org) `DataFrame` and `Series` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f57f10d-44b7-4846-82e5-5cc006b9f915",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.dask # noqa\n",
"import dask\n",
"\n",
"df_dask = dask.dataframe.from_pandas(df_pandas, npartitions=2)\n",
"df_dask"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5452eb4b-eec4-4b35-8739-235c89993fb7",
"metadata": {},
"outputs": [],
"source": [
"# Dask DataFrame\n",
"df_dask.hvplot.line(height=150)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97412fc0-e1f0-4f70-85b9-e9cbf1a2b7b5",
"metadata": {},
"outputs": [],
"source": [
"# Dask Series\n",
"s_dask = df_dask['A']\n",
"s_dask.hvplot.line(height=150)"
]
},
{
"cell_type": "markdown",
"id": "722a8efb-7c3b-4fa8-91b1-b5cbdabfa076",
"metadata": {},
"source": [
"#### GeoPandas"
]
},
{
"cell_type": "markdown",
"id": "19203932-5fff-4f27-8832-0ecda9d11465",
"metadata": {},
"source": [
"`.hvplot()` supports [GeoPandas](https://geopandas.org) `GeoDataFrame` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f9172be4-e06c-474a-8153-2aeee63ae864",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.pandas # noqa\n",
"import geopandas as gpd\n",
"\n",
"p_geometry = gpd.points_from_xy(\n",
" x=[12.45339, 12.44177, 9.51667, 6.13000],\n",
" y=[41.90328, 43.93610, 47.13372, 49.61166],\n",
" crs='EPSG:4326'\n",
")\n",
"p_names = ['Vatican City', 'San Marino', 'Vaduz', 'Luxembourg']\n",
"gdf = gpd.GeoDataFrame(dict(name=p_names), geometry=p_geometry)\n",
"gdf.head(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9eb04f03-89b4-4550-9a4e-cb8d762b65a8",
"metadata": {},
"outputs": [],
"source": [
"# GeoPandas GeoDataFrame\n",
"gdf.hvplot.points(geo=True, tiles='CartoLight', frame_height=150, data_aspect=0.5)"
]
},
{
"cell_type": "markdown",
"id": "4e445931-4b70-42e2-921c-e4d52961e8db",
"metadata": {},
"source": [
"#### Ibis"
]
},
{
"cell_type": "markdown",
"id": "3b841cd0-08fe-46b9-89c6-b8ce2c1376d5",
"metadata": {},
"source": [
"[Ibis](https://ibis-project.org/) is the \"portable Python dataframe library\", it provides a unified interface to many data backends (e.g. DuckDB, SQLite, SnowFlake, Google BigQuery). `.hvplot()` supports [Ibis](https://ibis-project.org/) `Expr` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "054bf27d-1f7b-4317-b853-3edab5c95d66",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.ibis # noqa\n",
"import ibis\n",
"\n",
"table = ibis.memtable(df_pandas.reset_index())\n",
"table"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e7e35256-8f62-4482-9108-35601d56035f",
"metadata": {},
"outputs": [],
"source": [
"# Ibis Expr\n",
"table.hvplot.line(x='index', height=150)"
]
},
{
"cell_type": "markdown",
"id": "df70157f-61de-4b2c-b53f-912cbde2a214",
"metadata": {},
"source": [
"#### Polars"
]
},
{
"cell_type": "markdown",
"id": "7474a792-2cfd-4139-a1cd-872f913fa07b",
"metadata": {},
"source": [
":::{note}\n",
"Added in version `0.9.0`.\n",
":::\n",
"\n",
":::{important}\n",
"While other data sources like `Pandas` or `Dask` have built-in support in HoloViews, as of version 1.17.1 this is not yet the case for `Polars`. You can track this [issue](https://github.com/holoviz/holoviews/issues/5939) to follow the evolution of this feature in HoloViews. Internally hvPlot simply selects the columns that contribute to the plot and casts them to a Pandas object using Polars' `.to_pandas()` method.\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8b0b03e7-2ada-4412-a0f2-7405aa6de4e8",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.polars # noqa \n",
"import polars\n",
"\n",
"df_polars = polars.from_pandas(df_pandas)\n",
"df_polars.head(2)"
]
},
{
"cell_type": "markdown",
"id": "c2bc769d-22b6-4d71-96cd-cf615200874e",
"metadata": {},
"source": [
"`.hvplot()` supports [Polars](https://www.pola.rs/) `DataFrame`, `LazyFrame` and `Series` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "63044ddf-6b5b-4588-9c79-4d92eee05f64",
"metadata": {},
"outputs": [],
"source": [
"# Polars DataFrame\n",
"df_polars.hvplot.line(y=['A', 'B', 'C', 'D'], height=150)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9dcf2346-03e9-4ab4-88e8-6a312ff50ea3",
"metadata": {},
"outputs": [],
"source": [
"# Polars LazyFrame\n",
"df_polars.lazy().hvplot.line(y=['A', 'B', 'C', 'D'], height=150)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3fd36092-f65f-480e-a0b7-f5a242eb4dff",
"metadata": {},
"outputs": [],
"source": [
"# Polars Series\n",
"df_polars['A'].hvplot.line(height=150)"
]
},
{
"cell_type": "markdown",
"id": "efc2f45e",
"metadata": {},
"source": [
"#### DuckDB"
]
},
{
"cell_type": "markdown",
"id": "db91860c",
"metadata": {},
"source": [
":::{note}\n",
"Added in version `0.11.0`.\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d6460d0",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"df_pandas = pd.DataFrame(np.random.randn(1000, 4), columns=list('ABCD')).cumsum()\n",
"df_pandas.head(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21638d45",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.duckdb # noqa \n",
"import duckdb\n",
"\n",
"connection = duckdb.connect(':memory:')\n",
"relation = duckdb.from_df(df_pandas, connection=connection)\n",
"relation.to_view(\"example_view\");"
]
},
{
"cell_type": "markdown",
"id": "40b56f16",
"metadata": {},
"source": [
"`.hvplot()` supports [DuckDB](https://duckdb.org/docs/api/python/overview.html) `DuckDBPyRelation` and `DuckDBConnection` objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f588e3fe",
"metadata": {},
"outputs": [],
"source": [
"relation.hvplot.line(y=['A', 'B', 'C', 'D'], height=150)"
]
},
{
"cell_type": "markdown",
"id": "68a47856",
"metadata": {},
"source": [
"`DuckDBPyRelation` is a bit more optimized because it handles column subsetting directly within DuckDB before the data is converted to a `pd.DataFrame`.\n",
"\n",
"So, it's a good idea to use the `connection.sql()` method when possible, which gives you a `DuckDBPyRelation`, instead of `connection.execute()`, which returns a `DuckDBPyConnection`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "214c60ee",
"metadata": {},
"outputs": [],
"source": [
"sql_expr = \"SELECT * FROM example_view WHERE A > 0 AND B > 0\"\n",
"connection.sql(sql_expr).hvplot.line(y=['A', 'B'], hover_cols=[\"C\"], height=150) # subsets A, B, C"
]
},
{
"cell_type": "markdown",
"id": "2a2f61d4",
"metadata": {},
"source": [
"Alternatively, you can directly subset the desired columns in the SQL expression."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5ce25c3d",
"metadata": {},
"outputs": [],
"source": [
"sql_expr = \"SELECT A, B, C FROM example_view WHERE A > 0 AND B > 0\"\n",
"connection.execute(sql_expr).hvplot.line(y=['A', 'B'], hover_cols=[\"C\"], height=150)"
]
},
{
"cell_type": "markdown",
"id": "25a6e724-6a84-4bff-9108-ac71dcfa9116",
"metadata": {},
"source": [
"#### Rapids cuDF"
]
},
{
"cell_type": "markdown",
"id": "39a94cd3-761e-41dd-8a8a-dc0438239254",
"metadata": {},
"source": [
":::{important}\n",
"[Rapids cuDF](https://docs.rapids.ai/api/cudf) is a Python **GPU** DataFrame library. Neither hvPlot's nor HoloViews' test suites currently run on a GPU part of their CI, as of versions 0.9.0 and 1.17.1, respectively. This is due to the non availability of machines equipped with a GPU on the free CI system we rely on (Github Actions). Therefore it's possible that support for cuDF gets degraded in hvPlot without us noticing it immediately. Please report any issue you might encounter.\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "a4639f12-d92f-413c-9330-5063ed0a4d30",
"metadata": {},
"source": [
"`.hvplot()` supports [cuDF](https://docs.rapids.ai/api/cudf) `DataFrame` and `Series` objects."
]
},
{
"cell_type": "markdown",
"id": "1f34dbde-5805-4bde-a694-291fef565e01",
"metadata": {},
"source": [
"#### Fugue"
]
},
{
"cell_type": "markdown",
"id": "2fa0d745-d683-4e53-a3b2-4f14d4e365d8",
"metadata": {},
"source": [
":::{admonition} Experimental\n",
":class: caution\n",
"[Fugue](https://fugue-tutorials.readthedocs.io/) support, added in version `0.9.0`, is experimental and may change in future versions.\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "e403ab84-f1ad-4a13-bcb4-e47ba7207c6d",
"metadata": {},
"source": [
"hvPlot adds the `hvplot` plotting extension to FugueSQL."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4168cb11-83f9-4975-919a-e7b194c893a6",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.fugue # noqa\n",
"import fugue\n",
"\n",
"fugue.api.fugue_sql(\n",
" \"\"\"\n",
" OUTPUT df_pandas USING hvplot:line(\n",
" height=150,\n",
" )\n",
" \"\"\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "6f573c28-c186-437c-804e-893146269cf5",
"metadata": {},
"source": [
"### Multidimensional"
]
},
{
"cell_type": "markdown",
"id": "8c10dc76-0746-468f-b390-4bb71a5c5b40",
"metadata": {},
"source": [
"#### Xarray"
]
},
{
"cell_type": "markdown",
"id": "00d4be9a-7aba-4cdc-9d9f-bb324b3e7d0e",
"metadata": {},
"source": [
"`.hvplot()` supports [XArray](https://xarray.pydata.org) `Dataset` and `DataArray` labelled multidimensional objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "04ac5ebd-5365-4254-8b32-4c51ac59dd0c",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.xarray # noqa\n",
"import xarray as xr\n",
"\n",
"ds = xr.Dataset({\n",
" 'A': (['x', 'y'], np.random.randn(100, 100)),\n",
" 'B': (['x', 'y'], np.random.randn(100, 100))},\n",
" coords={'x': np.arange(100), 'y': np.arange(100)}\n",
")\n",
"ds"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1f9613f6-cf2c-4049-b6ac-42ad4ccf5fd9",
"metadata": {},
"outputs": [],
"source": [
"# Xarray Dataset\n",
"ds.hvplot.hist(height=150)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f0cd739d-8450-4a12-a0f5-7cddc1f85fc2",
"metadata": {},
"outputs": [],
"source": [
"# Xarray DataArray\n",
"ds['A'].hvplot.image(height=150)"
]
},
{
"cell_type": "markdown",
"id": "2530f2da-2287-43d7-998d-bfb3eeb64d80",
"metadata": {},
"source": [
"### Catalog"
]
},
{
"cell_type": "markdown",
"id": "55668697-f5f5-40e6-9fd2-f023bea3e9dc",
"metadata": {},
"source": [
"#### Intake"
]
},
{
"cell_type": "markdown",
"id": "7c01a461-5c22-48a3-b5e1-a2a3716c5bf4",
"metadata": {},
"source": [
"`.hvplot()` supports [Intake](https://github.com/ContinuumIO/intake) `DataSource` objects."
]
},
{
"cell_type": "markdown",
"id": "111f4441-f5b2-4355-92aa-de79c4fe30c7",
"metadata": {},
"source": [
"### Streaming"
]
},
{
"cell_type": "markdown",
"id": "53a878cc-265c-4787-86a4-9870a22dc2b2",
"metadata": {},
"source": [
"#### Streamz"
]
},
{
"cell_type": "markdown",
"id": "e22cdb0f-7522-4976-b891-f72bf50fb767",
"metadata": {},
"source": [
"`.hvplot()` supports [Streamz](https://streamz.readthedocs.io) `DataFrame`, `DataFrames`, `Series` and `Seriess` objects."
]
},
{
"cell_type": "markdown",
"id": "cbb521df-9cc0-462e-a56e-34034c3fb3e5",
"metadata": {},
"source": [
"### Graph"
]
},
{
"cell_type": "markdown",
"id": "50aa859a-4fa4-4f49-a47e-381aa8071be3",
"metadata": {},
"source": [
"#### NetworkX"
]
},
{
"cell_type": "markdown",
"id": "4ead472d-c9c9-48e4-874e-b82c37519e2a",
"metadata": {},
"source": [
"The hvPlot [NetworkX](https://networkx.github.io) plotting API is meant as a drop-in replacement for the `networkx.draw` methods. The `draw` and other `draw_<>` methods are available in the `hvplot.networkx` module."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a912200f-142a-4137-8b47-8fd8fa6340ff",
"metadata": {},
"outputs": [],
"source": [
"import hvplot.networkx as hvnx\n",
"import networkx as nx\n",
"\n",
"G = nx.petersen_graph()\n",
"hvnx.draw(G, with_labels=True, height=150)"
]
},
{
"cell_type": "markdown",
"id": "2069924f-c9c9-4b3a-91f2-664f2e435c19",
"metadata": {},
"source": [
"## Plotting extensions"
]
},
{
"cell_type": "markdown",
"id": "5d8c163c-40e5-4725-9d9e-80e131c27bc6",
"metadata": {},
"source": [
"hvPlot is capable of producing plots with [Bokeh](https://www.bokeh.org) (default, interactive), [Matplotlib](https://matplotlib.org) (static) and [Plotly](https://plotly.com/python/) (interactive). Under the hood, hvPlot delegates plotting to HoloViews which itself calls these plotting libraries. This is why we call hvPlot a high-level plotting library!\n",
"\n",
"Follow the [Plotting Extensions Guide](Plotting_Extensions.ipynb) for more information."
]
},
{
"cell_type": "markdown",
"id": "142f2075-97c7-4618-9d63-0ec89297562f",
"metadata": {},
"source": [
":::{note}\n",
"Similarly to having to support many data sources, supporting three plotting extensions is hard work! We are aware they are not supported equivalently, you will get best support for Bokeh, followed by Matplotlib and finally Plotly. If you encounter any issue with a specific plotting extension please report it on GitHub, we always welcome Pull Requests too!\n",
":::"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}