{ "cells": [ { "cell_type": "markdown", "id": "a229bf0b-97ba-41ca-b68f-3011ca82198d", "metadata": {}, "source": [ "# Supported data libraries" ] }, { "cell_type": "code", "execution_count": null, "id": "42ebab2c-ee59-4157-9b01-c1bb7988b407", "metadata": { "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "# hidden on the website\n", "import numpy as np\n", "\n", "np.random.seed(1)" ] }, { "cell_type": "markdown", "id": "4471a77a-8fca-4af4-94f5-d4c753dc73dd", "metadata": {}, "source": [ "The `.hvplot()` [plotting API](api-plotting) supports a wide range of data sources. For most of them, a special import can be executed to register the `.hvplot` accessor on specific objects. 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.\n", "\n", "The following table provides a summary of the data sources supported by hvPlot. The *HoloViews interface* column indicates whether HoloViews offers [an interface](inv:holoviews#holoviews.core.data) for that data source, meaning the data would in most cases not be converted to another type until the very last steps of the rendering process. When no interface is available for a data type, hvPlot internally casts the data to a supported type, for instance `polars` objects are casted upfront to `pandas` objects." ] }, { "cell_type": "markdown", "id": "5f0d3dcc", "metadata": {}, "source": [ "| Source | Module | Type | HoloViews interface | Comment |\n", "| --------------------------------- | ---------------- | ----------------- | ------------------- | ----------------------------- |\n", "| [Pandas](#libraries-pandas) | `hvplot.pandas` | Tabular | ✅ | |\n", "| [Dask](#libraries-dask) | `hvplot.dask` | Tabular | ✅ | |\n", "| [Geopandas](#libraries-geopandas) | `hvplot.pandas` | Tabular | ✅ | |\n", "| [Ibis](#libraries-ibis) | `hvplot.ibis` | Tabular | ✅ | |\n", "| [Polars](#libraries-polars) | `hvplot.polars` | Tabular | ❌ | To Pandas |\n", "| [DuckDB](#libraries-duckdb) | `hvplot.duckdb` | Tabular | ❌ | To Pandas |\n", "| [RAPIDS cuDF](#libraries-cudf) | `hvplot.cudf` | Tabular | ✅ | GPU |\n", "| [Fugue](#libraries-fugue) | `hvplot.fugue` | Tabular | ❌ | Experimental |\n", "| [Xarray](#libraries-xarray) | `hvplot.xarray` | Multidimensional | ✅ | |\n", "| [Intake](#libraries-intake) | `hvplot.intake` | Catalog | ❌ | |\n", "| [Streamz](#libraries-streamz) | `hvplot.streamz` | Streaming | ✅ | |\n", "| [NetworkX](#libraries-networkx) | - | Graph | - | [Different API](api-networkx) |\n" ] }, { "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": [ "(libraries-pandas)=\n", "### Pandas\n", "\n", "`.hvplot()` supports [Pandas](https://pandas.pydata.org) `DataFrame` and `Series` objects. hvPlot can also be registered as Pandas' default plotting backend to delegate Pandas `.plot()` calls to hvPlot directly instead of to Pandas' Matplotlib backend. Find out more about [hvPlot's compatibility with Pandas' plotting interface](./api_compatibility/pandas/index.ipynb)." ] }, { "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": [ "(libraries-dask)=\n", "### [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": [ "(libraries-geopandas)=\n", "### 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": [ "(libraries-ibis)=\n", "### 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": [ "(libraries-polars)=\n", "### 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": [ "(libraries-duckdb)=\n", "### 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": [ "(libraries-cudf)=\n", "### 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": [ "(libraries-fugue)=\n", "### 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": [ "(libraries-xarray)=\n", "### 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": [ "(libraries-intake)=\n", "### Intake" ] }, { "cell_type": "markdown", "id": "7c01a461-5c22-48a3-b5e1-a2a3716c5bf4", "metadata": {}, "source": [ "`.hvplot()` supports [Intake](https://github.com/intake/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": [ "(libraries-streamz)=\n", "### 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": [ "(libraries-networkx)=\n", "### 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)" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }