├── .git-blame-ignore-revs ├── .git_archival.txt ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml └── workflows │ ├── auto_triage.yml │ ├── build.yaml │ ├── docs.yaml │ ├── nightly_lock.yaml │ └── test.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── binder ├── environment.yml └── postBuild ├── doc ├── _ext │ ├── backend_styling_options.py │ └── plotting_options_table.py ├── _static │ ├── custom.css │ ├── favicon.ico │ ├── home │ │ ├── bokeh.gif │ │ ├── dask.gif │ │ ├── explorer.gif │ │ ├── geo.gif │ │ ├── geopandas.gif │ │ ├── intake.gif │ │ ├── interactive_hvplot.gif │ │ ├── interactive_pandas.gif │ │ ├── interactive_xarray.gif │ │ ├── large_data.gif │ │ ├── layout.gif │ │ ├── matplotlib.png │ │ ├── networkx.gif │ │ ├── overlay.png │ │ ├── pandas.gif │ │ ├── plotly.gif │ │ ├── widgets.gif │ │ └── xarray.gif │ ├── images │ │ ├── heat_and_trees.png │ │ └── portfolio.png │ ├── logo.png │ ├── logo_horizontal.svg │ ├── logo_stacked.svg │ └── patch_templates │ │ └── sourcelink.html ├── about.md ├── assets │ ├── console.png │ ├── console_server.gif │ ├── diagram.png │ ├── diagram.svg │ ├── hvplot-wm.png │ └── streamz_demo.gif ├── conf.py ├── conftest.py ├── developer_guide.md ├── governance │ └── project-docs │ │ ├── CONTRIBUTING.md │ │ ├── GOVERNANCE.md │ │ ├── LICENSE.md │ │ └── MEMBERS.md ├── index.md ├── ref │ ├── api │ │ ├── index.md │ │ └── manual │ │ │ ├── hvplot.hvPlot.area.ipynb │ │ │ ├── hvplot.hvPlot.bar.ipynb │ │ │ ├── hvplot.hvPlot.barh.ipynb │ │ │ ├── hvplot.hvPlot.bivariate.ipynb │ │ │ ├── hvplot.hvPlot.box.ipynb │ │ │ ├── hvplot.hvPlot.contour.ipynb │ │ │ ├── hvplot.hvPlot.contourf.ipynb │ │ │ ├── hvplot.hvPlot.dataset.ipynb │ │ │ ├── hvplot.hvPlot.density.md │ │ │ ├── hvplot.hvPlot.errorbars.ipynb │ │ │ ├── hvplot.hvPlot.heatmap.ipynb │ │ │ ├── hvplot.hvPlot.hexbin.ipynb │ │ │ ├── hvplot.hvPlot.hist.ipynb │ │ │ ├── hvplot.hvPlot.image.ipynb │ │ │ ├── hvplot.hvPlot.kde.ipynb │ │ │ ├── hvplot.hvPlot.labels.ipynb │ │ │ ├── hvplot.hvPlot.line.ipynb │ │ │ ├── hvplot.hvPlot.ohlc.ipynb │ │ │ ├── hvplot.hvPlot.paths.ipynb │ │ │ ├── hvplot.hvPlot.points.ipynb │ │ │ ├── hvplot.hvPlot.polygons.ipynb │ │ │ ├── hvplot.hvPlot.quadmesh.ipynb │ │ │ ├── hvplot.hvPlot.rgb.ipynb │ │ │ ├── hvplot.hvPlot.scatter.ipynb │ │ │ ├── hvplot.hvPlot.step.ipynb │ │ │ ├── hvplot.hvPlot.table.ipynb │ │ │ ├── hvplot.hvPlot.vectorfield.ipynb │ │ │ ├── hvplot.hvPlot.violin.ipynb │ │ │ ├── hvplot.plotting.andrews_curves.ipynb │ │ │ ├── hvplot.plotting.lag_plot.ipynb │ │ │ ├── hvplot.plotting.parallel_coordinates.ipynb │ │ │ └── hvplot.plotting.scatter_matrix.ipynb │ ├── api_compatibility │ │ ├── index.md │ │ └── pandas │ │ │ ├── Pandas_API.ipynb │ │ │ └── index.ipynb │ ├── data_libraries.ipynb │ ├── deprecations.md │ ├── index.md │ ├── installation.md │ ├── plotting_extensions.ipynb │ └── plotting_options │ │ ├── data.ipynb │ │ ├── grid_legend.ipynb │ │ ├── index.md │ │ └── size_layout.ipynb ├── reference │ ├── geopandas │ │ ├── points.ipynb │ │ └── polygons.ipynb │ ├── tabular │ │ ├── andrewscurves.ipynb │ │ ├── area.ipynb │ │ ├── bar.ipynb │ │ ├── barh.ipynb │ │ ├── bivariate.ipynb │ │ ├── box.ipynb │ │ ├── errorbars.ipynb │ │ ├── heatmap.ipynb │ │ ├── hexbin.ipynb │ │ ├── hist.ipynb │ │ ├── kde.ipynb │ │ ├── labels.ipynb │ │ ├── lagplot.ipynb │ │ ├── line.ipynb │ │ ├── ohlc.ipynb │ │ ├── parallelcoordinates.ipynb │ │ ├── paths.ipynb │ │ ├── scatter.ipynb │ │ ├── scattermatrix.ipynb │ │ ├── step.ipynb │ │ ├── table.ipynb │ │ └── violin.ipynb │ └── xarray │ │ ├── bar.ipynb │ │ ├── contour.ipynb │ │ ├── contourf.ipynb │ │ ├── hist.ipynb │ │ ├── image.ipynb │ │ ├── kde.ipynb │ │ ├── line.ipynb │ │ ├── quadmesh.ipynb │ │ ├── rgb.ipynb │ │ ├── vectorfield.ipynb │ │ └── violin.ipynb ├── releases.md ├── roadmap.md ├── topics.html ├── tutorials │ ├── getting_started.ipynb │ ├── getting_started_pandas.ipynb │ └── index.md └── user_guide │ ├── Explorer.ipynb │ ├── Geographic_Data.ipynb │ ├── Gridded_Data.ipynb │ ├── Interactive.ipynb │ ├── Introduction.ipynb │ ├── Large_Timeseries.ipynb │ ├── NetworkX.ipynb │ ├── Plotting.ipynb │ ├── Plotting_Extensions.ipynb │ ├── Plotting_with_Matplotlib.ipynb │ ├── Plotting_with_Plotly.ipynb │ ├── Statistical_Plots.ipynb │ ├── Streaming.ipynb │ ├── Subplots.ipynb │ ├── Timeseries_Data.ipynb │ ├── Viewing.ipynb │ ├── Widgets.ipynb │ ├── images │ └── simple.svg │ └── index.md ├── hvplot ├── __init__.py ├── backend_transforms.py ├── converter.py ├── cudf.py ├── dask.py ├── data │ └── crime.csv ├── datasets.yaml ├── duckdb.py ├── fugue.py ├── ibis.py ├── intake.py ├── interactive.py ├── networkx.py ├── pandas.py ├── plotting │ ├── __init__.py │ ├── andrews_curves.py │ ├── core.py │ ├── lag_plot.py │ ├── parallel_coordinates.py │ └── scatter_matrix.py ├── polars.py ├── sample_data.py ├── streamz.py ├── tests │ ├── __init__.py │ ├── conftest.py │ ├── data │ │ ├── README.md │ │ └── RGB-red.byte.tif │ ├── plotting │ │ ├── __init__.py │ │ ├── testandrewscurves.py │ │ ├── testcore.py │ │ ├── testohlc.py │ │ └── testscattermatrix.py │ ├── test_links.py │ ├── testbackend_transforms.py │ ├── testcharts.py │ ├── testdeprecations.py │ ├── testdocstring.py │ ├── testfugue.py │ ├── testgeo.py │ ├── testgeowithoutgv.py │ ├── testgridplots.py │ ├── testhelp.py │ ├── testibis.py │ ├── testinteractive.py │ ├── testnetworkx.py │ ├── testoperations.py │ ├── testoptions.py │ ├── testoverrides.py │ ├── testpanel.py │ ├── testpatch.py │ ├── testpatchsignature.py │ ├── testplotting.py │ ├── teststatplots.py │ ├── teststreaming.py │ ├── testtransforms.py │ ├── testui.py │ ├── testutil.py │ └── util.py ├── ui.py ├── util.py ├── utilities.py └── xarray.py ├── pixi.toml ├── pyproject.toml └── scripts ├── conda ├── build.sh └── recipe │ └── meta.yaml ├── download_data.py └── sync_git_tags.py /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Run this command to always ignore formatting commits in `git blame` 2 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 3 | 4 | # Ignore linting/formatting with ruff initial PR (https://github.com/holoviz/hvplot/pull/1320) 5 | 6c33e47b740e0a5093688a855e99559245c553fd 6 | -------------------------------------------------------------------------------- /.git_archival.txt: -------------------------------------------------------------------------------- 1 | node: 25e6456e3fab40205f442b1df41f6422e560808f 2 | node-date: 2025-05-27T19:39:17+02:00 3 | describe-name: v0.11.3-12-g25e6456e3 4 | ref-names: HEAD -> main 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # For setuptools_scm with .git_archival.txt 2 | .git_archival.txt export-subst 3 | # Line Endings configuration file for Git 4 | # Set the default behavior, in case people don't have or can't have core.autocrlf set. 5 | * text=auto 6 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to hvPlot 2 | 3 | Please follow the [contributor guide](https://hvplot.holoviz.org/developer_guide/index.html). 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: holoviz 4 | -------------------------------------------------------------------------------- /.github/workflows/auto_triage.yml: -------------------------------------------------------------------------------- 1 | name: Auto-label new issues with "TRIAGE" 2 | 3 | on: 4 | issues: 5 | types: 6 | - reopened 7 | - opened 8 | jobs: 9 | add-triage-label: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | steps: 14 | - run: gh issue edit "$NUMBER" --add-label "$LABELS" 15 | env: 16 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | GH_REPO: ${{ github.repository }} 18 | NUMBER: ${{ github.event.issue.number }} 19 | LABELS: TRIAGE 20 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: packages 2 | on: 3 | push: 4 | tags: 5 | - 'v[0-9]+.[0-9]+.[0-9]+' 6 | - 'v[0-9]+.[0-9]+.[0-9]+a[0-9]+' 7 | - 'v[0-9]+.[0-9]+.[0-9]+b[0-9]+' 8 | - 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+' 9 | # Dry-run only 10 | workflow_dispatch: 11 | schedule: 12 | - cron: '0 15 * * SUN' 13 | 14 | env: 15 | PYTHON_VERSION: "3.11" 16 | 17 | defaults: 18 | run: 19 | shell: bash -e {0} 20 | 21 | jobs: 22 | pixi_lock: 23 | name: Pixi lock 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: holoviz-dev/holoviz_tasks/pixi_lock@v0 27 | 28 | conda_build: 29 | name: Build Conda 30 | needs: [pixi_lock] 31 | runs-on: "ubuntu-latest" 32 | steps: 33 | - uses: holoviz-dev/holoviz_tasks/pixi_install@v0 34 | with: 35 | environments: "build" 36 | download-data: false 37 | install: false 38 | - name: conda build 39 | run: pixi run -e build build-conda 40 | - name: Set environment variables 41 | run: | 42 | echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV 43 | echo "CONDA_FILE=$(ls dist/*.tar.bz2)" >> $GITHUB_ENV 44 | - name: conda dev upload 45 | if: github.event_name == 'push' && (contains(env.TAG, 'a') || contains(env.TAG, 'b') || contains(env.TAG, 'rc')) 46 | run: pixi run -e build publish-conda --token ${{ secrets.CONDA_UPLOAD_TOKEN }} upload --user pyviz --label=dev $CONDA_FILE 47 | - name: conda main upload 48 | if: github.event_name == 'push' && (!(contains(env.TAG, 'a') || contains(env.TAG, 'b') || contains(env.TAG, 'rc'))) 49 | run: pixi run -e build publish-conda --token ${{ secrets.CONDA_UPLOAD_TOKEN }} upload --user pyviz --label=dev --label=main $CONDA_FILE 50 | 51 | pip_build: 52 | name: Build PyPI 53 | needs: [pixi_lock] 54 | runs-on: "ubuntu-latest" 55 | permissions: 56 | id-token: write 57 | steps: 58 | - uses: holoviz-dev/holoviz_tasks/pixi_install@v0 59 | with: 60 | environments: "build" 61 | download-data: false 62 | install: false 63 | - name: Build package 64 | run: pixi run -e build build-pip 65 | - name: Publish to PyPI 66 | if: github.event_name == 'push' 67 | uses: pypa/gh-action-pypi-publish@release/v1 68 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: docs 2 | on: 3 | push: 4 | tags: 5 | - 'v[0-9]+.[0-9]+.[0-9]+' 6 | - 'v[0-9]+.[0-9]+.[0-9]+a[0-9]+' 7 | - 'v[0-9]+.[0-9]+.[0-9]+b[0-9]+' 8 | - 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+' 9 | workflow_dispatch: 10 | inputs: 11 | target: 12 | description: 'Site to build and deploy' 13 | type: choice 14 | options: 15 | - dev 16 | - main 17 | - dryrun 18 | required: true 19 | default: dryrun 20 | schedule: 21 | - cron: '0 15 * * SUN' 22 | 23 | defaults: 24 | run: 25 | shell: bash -e {0} 26 | 27 | env: 28 | PYTHON_VERSION: "3.11" 29 | 30 | jobs: 31 | pixi_lock: 32 | name: Pixi lock 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: holoviz-dev/holoviz_tasks/pixi_lock@v0 36 | 37 | docs_build: 38 | name: Build Documentation 39 | runs-on: 'macos-latest' 40 | timeout-minutes: 120 41 | env: 42 | DISPLAY: ":99.0" 43 | steps: 44 | - uses: holoviz-dev/holoviz_tasks/pixi_install@v0 45 | with: 46 | environments: docs 47 | - name: Build documentation 48 | run: pixi run -e docs docs-build 49 | - name: Set and echo git ref 50 | id: vars 51 | run: | 52 | echo "Deploying from ref ${GITHUB_REF#refs/*/}" 53 | echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT 54 | - name: report failure 55 | if: failure() 56 | run: cat /tmp/sphinx-*.log | tail -n 100 57 | - name: Deploy dev 58 | uses: peaceiris/actions-gh-pages@v4 59 | if: | 60 | (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'dev') || 61 | (github.event_name == 'push' && (contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc'))) 62 | with: 63 | personal_token: ${{ secrets.ACCESS_TOKEN }} 64 | external_repository: holoviz-dev/hvplot 65 | publish_dir: ./builtdocs 66 | force_orphan: true 67 | exclude_assets: '.doctrees' 68 | - name: Deploy main 69 | if: | 70 | (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'main') || 71 | (github.event_name == 'push' && !(contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc'))) 72 | uses: peaceiris/actions-gh-pages@v4 73 | with: 74 | github_token: ${{ secrets.GITHUB_TOKEN }} 75 | publish_dir: ./builtdocs 76 | cname: hvplot.holoviz.org 77 | force_orphan: true 78 | exclude_assets: '.doctrees' 79 | 80 | pip_build_docs: 81 | name: Build Documentation (pip) 82 | runs-on: 'ubuntu-latest' 83 | timeout-minutes: 120 84 | env: 85 | DESC: "Documentation build" 86 | MPLBACKEND: "Agg" 87 | MOZ_HEADLESS: 1 88 | DISPLAY: ":99.0" 89 | steps: 90 | - uses: actions/checkout@v4 91 | with: 92 | fetch-depth: 0 93 | - uses: actions/setup-python@v5 94 | with: 95 | python-version: ${{ env.PYTHON_VERSION }} 96 | - name: install 97 | run: pip install -v --prefer-binary -e ."[doc, examples, geo]" 98 | - name: pip list 99 | run: pip list 100 | - name: Set and echo git ref 101 | id: vars 102 | run: | 103 | echo "Deploying from ref ${GITHUB_REF#refs/*/}" 104 | echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT 105 | - name: build docs 106 | run: sphinx-build -j auto -b html doc builtdocs 107 | - name: report failure 108 | if: failure() 109 | run: cat /tmp/sphinx-*.log | tail -n 100 110 | -------------------------------------------------------------------------------- /.github/workflows/nightly_lock.yaml: -------------------------------------------------------------------------------- 1 | name: nightly_lock 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | env: 8 | PACKAGE: "hvplot" 9 | 10 | jobs: 11 | pixi_lock: 12 | if: ${{ !github.event.repository.fork }} 13 | name: Pixi lock 14 | runs-on: ubuntu-latest 15 | timeout-minutes: 5 16 | steps: 17 | - uses: holoviz-dev/holoviz_tasks/pixi_lock@v0 18 | - name: Upload lock-file to S3 19 | env: 20 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 21 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 22 | AWS_DEFAULT_REGION: "eu-west-1" 23 | run: | 24 | zip $(date +%Y-%m-%d).zip pixi.lock pixi.toml 25 | aws s3 cp ./$(date +%Y-%m-%d).zip s3://assets.holoviz.org/lock/$PACKAGE/ 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # dotenv 84 | .env 85 | 86 | # virtualenv 87 | .venv 88 | venv/ 89 | ENV/ 90 | 91 | # Spyder project settings 92 | .spyderproject 93 | .spyproject 94 | 95 | # Rope project settings 96 | .ropeproject 97 | 98 | # mkdocs documentation 99 | /site 100 | 101 | # mypy 102 | .mypy_cache/ 103 | 104 | # nbsite 105 | # these files normally shouldn't be checked in as they should be 106 | # dynamically built from notebooks 107 | doc/**/*.rst 108 | doc/**/*.json 109 | # thumbnails are downloaded on the fly 110 | doc/reference/*/thumbnails/ 111 | # this dir contains the whole website and should not be checked in on main 112 | builtdocs/ 113 | # mystnb 114 | jupyter_execute/ 115 | 116 | # pip 117 | pip-wheel-metadata/ 118 | 119 | # IDE 120 | /.vscode 121 | 122 | # MacOS 123 | .DS_Store 124 | 125 | # Examples artefacts 126 | doc/user_guide/plot.html 127 | 128 | # setuptools_scm 129 | hvplot/_version.py 130 | 131 | # pixi 132 | .pixi 133 | pixi.lock 134 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_stages: [pre-commit] 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v5.0.0 5 | hooks: 6 | - id: check-builtin-literals 7 | - id: check-case-conflict 8 | - id: check-docstring-first 9 | - id: check-executables-have-shebangs 10 | - id: check-toml 11 | - id: detect-private-key 12 | - id: end-of-file-fixer 13 | exclude: (\.min\.js$|\.svg$) 14 | - id: trailing-whitespace 15 | - repo: https://github.com/astral-sh/ruff-pre-commit 16 | rev: v0.11.8 17 | hooks: 18 | - id: ruff 19 | - id: ruff-format 20 | exclude: \.ipynb$ 21 | - repo: https://github.com/hoxbro/clean_notebook 22 | rev: v0.1.17 23 | hooks: 24 | - id: clean-notebook 25 | args: [-i, tags] 26 | - repo: https://github.com/codespell-project/codespell 27 | rev: v2.4.1 28 | hooks: 29 | - id: codespell 30 | exclude: (\.min\.js$|\.svg$|\.html$) 31 | additional_dependencies: 32 | - tomli 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | For the release notes, please consult ./doc/releases.md 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | For the code of conduct, see [HoloViz/HoloViz - CODE_OF_CONDUCT.md](https://github.com/holoviz/holoviz/blob/hvplot-gov/CODE_OF_CONDUCT.md). 4 | 5 | The hvPlot Project’s equivalently named documents take precedence over any external materials referenced within this linked document above. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, HoloViz 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /binder/environment.yml: -------------------------------------------------------------------------------- 1 | name: hvplot 2 | channels: 3 | - conda-forge 4 | - nodefaults 5 | dependencies: 6 | - geoviews>=1.6.0 7 | - numba>=0.51.0 8 | - geopandas>=0.9.0 9 | - xarray>=0.18.2 10 | - networkx>=2.6.3 11 | - streamz>=0.3.0 12 | - intake>=0.6.5 13 | - intake-parquet>=0.2.3 14 | - intake-xarray>=0.5.0 15 | - dask>=2021.3.0 16 | - datashader>=0.6.5 17 | - notebook>=5.4 18 | - rasterio>=1.2.6 19 | - cartopy>= 0.18.0 20 | - pyproj>=3.0.1 21 | - s3fs>=2022.1.0 22 | - scipy>=1.5.3 23 | - pillow>=8.2.0 24 | - selenium>=3.141.0 25 | - spatialpandas>=0.4.3 26 | - scikit-image>=0.17.2 27 | - python-snappy>=0.6.0 28 | - pooch>=1.6.0 29 | - fiona>=1.8.18 30 | - pyepsg>=0.4.0 31 | - matplotlib 32 | - plotly 33 | - pygraphviz 34 | - pip 35 | - pip: 36 | - .. 37 | -------------------------------------------------------------------------------- /binder/postBuild: -------------------------------------------------------------------------------- 1 | bokeh sampledata 2 | -------------------------------------------------------------------------------- /doc/_ext/backend_styling_options.py: -------------------------------------------------------------------------------- 1 | from docutils import nodes 2 | from docutils.statemachine import StringList 3 | from sphinx.util.docutils import SphinxDirective 4 | 5 | import holoviews as hv 6 | 7 | from hvplot.util import _get_backend_style_options 8 | 9 | 10 | hv.extension('bokeh', 'matplotlib') 11 | 12 | 13 | class BackendStylingOptionsDirective(SphinxDirective): 14 | """ 15 | Display the Bokeh and Matplotlib styling options for a plot method 16 | in a tabs layout. 17 | 18 | .. backend-styling-options:: scatter 19 | """ 20 | 21 | has_content = False 22 | required_arguments = 1 23 | optional_arguments = 0 24 | final_argument_whitespace = True 25 | 26 | def run(self): 27 | input_string = self.arguments[0] 28 | 29 | bk_opts = _get_backend_style_options(input_string, 'bokeh') 30 | mpl_opts = _get_backend_style_options(input_string, 'matplotlib') 31 | bk_opts_info = ', '.join(bk_opts) 32 | mpl_opts_info = ', '.join(mpl_opts) 33 | # Sphinx-design syntax 34 | tab_content = f""" 35 | .. tab-set:: 36 | 37 | .. tab-item:: Bokeh 38 | 39 | {bk_opts_info} 40 | 41 | .. tab-item:: Matplotlib 42 | 43 | {mpl_opts_info} 44 | """ 45 | 46 | container = nodes.container() 47 | container['classes'] = ['backend-styling-options-container'] 48 | content_list = StringList(tab_content.splitlines(), source='') 49 | self.state.nested_parse(content_list, 0, container) 50 | return container.children 51 | 52 | 53 | def setup(app): 54 | app.add_directive('backend-styling-options', BackendStylingOptionsDirective) 55 | 56 | return { 57 | 'version': '0.1', 58 | 'parallel_read_safe': True, 59 | 'parallel_write_safe': True, 60 | } 61 | -------------------------------------------------------------------------------- /doc/_ext/plotting_options_table.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sphinx extension to display a table with the options of a specific 3 | options group of the converter. Requires numpydoc 4 | 5 | Usage: 6 | 7 | .. plotting-options-table:: Style Options 8 | """ 9 | 10 | import sys 11 | 12 | from textwrap import indent 13 | 14 | from hvplot.util import _get_docstring_group_parameters 15 | from sphinx.util.docutils import SphinxDirective 16 | 17 | 18 | class PlottingOptionsTableDirective(SphinxDirective): 19 | """ 20 | Directive to display a plotting option group in a Markdown table. 21 | 22 | .. plotting-options-table:: Data Options 23 | """ 24 | 25 | required_arguments = 1 26 | final_argument_whitespace = True 27 | 28 | def run(self): 29 | # Get the key passed to the directive 30 | options_group = self.arguments[0] 31 | parameters = _get_docstring_group_parameters(options_group) 32 | table_rst = ['.. list-table::', ' :header-rows: 1', ' :widths: 25 70', ''] 33 | table_rst.append(' * - ') 34 | table_rst.append(' Parameters') 35 | table_rst.append(' - ') 36 | table_rst.append(' Description') 37 | 38 | for param in parameters: 39 | desc = '\n'.join(param.desc) 40 | table_rst.append(' * - ') 41 | table_rst.append(f' **{param.name}** *({param.type})*') 42 | table_rst.append(' - ') 43 | table_rst.append(indent(desc, ' ' * 7)) 44 | 45 | raw_rst = '\n'.join(table_rst) 46 | 47 | parsed = self.parse_text_to_nodes(raw_rst) 48 | return parsed 49 | 50 | 51 | def setup(app): 52 | app.add_directive('plotting-options-table', PlottingOptionsTableDirective) 53 | 54 | return { 55 | 'version': '0.1', 56 | 'parallel_read_safe': True, 57 | 'parallel_write_safe': True, 58 | } 59 | 60 | 61 | if __name__ == '__main__': 62 | group = ' '.join(sys.argv[1:]) 63 | opts = _get_docstring_group_parameters(group) 64 | print(opts) 65 | -------------------------------------------------------------------------------- /doc/_static/custom.css: -------------------------------------------------------------------------------- 1 | :root[data-theme="light"] { 2 | --pst-color-primary: rgb(56,123,178); 3 | --pst-color-link: rgb(56,123,178); 4 | --pst-color-link-hover: rgb(254,203,56); 5 | } 6 | 7 | .sphx-glr-thumbcontainer { 8 | height: 210px; 9 | } 10 | 11 | .nav-link { 12 | white-space: nowrap; 13 | } 14 | 15 | .showcase-table { 16 | border-spacing: 15px 17 | } 18 | 19 | .showcase-table td { 20 | border: 0px; 21 | vertical-align: top; 22 | } 23 | 24 | .getting-started-button { 25 | border-radius: 6px !important; 26 | padding: 0.7em 3em !important; 27 | font-size: 1.2em; 28 | } 29 | -------------------------------------------------------------------------------- /doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/favicon.ico -------------------------------------------------------------------------------- /doc/_static/home/bokeh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/bokeh.gif -------------------------------------------------------------------------------- /doc/_static/home/dask.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/dask.gif -------------------------------------------------------------------------------- /doc/_static/home/explorer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/explorer.gif -------------------------------------------------------------------------------- /doc/_static/home/geo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/geo.gif -------------------------------------------------------------------------------- /doc/_static/home/geopandas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/geopandas.gif -------------------------------------------------------------------------------- /doc/_static/home/intake.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/intake.gif -------------------------------------------------------------------------------- /doc/_static/home/interactive_hvplot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/interactive_hvplot.gif -------------------------------------------------------------------------------- /doc/_static/home/interactive_pandas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/interactive_pandas.gif -------------------------------------------------------------------------------- /doc/_static/home/interactive_xarray.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/interactive_xarray.gif -------------------------------------------------------------------------------- /doc/_static/home/large_data.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/large_data.gif -------------------------------------------------------------------------------- /doc/_static/home/layout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/layout.gif -------------------------------------------------------------------------------- /doc/_static/home/matplotlib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/matplotlib.png -------------------------------------------------------------------------------- /doc/_static/home/networkx.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/networkx.gif -------------------------------------------------------------------------------- /doc/_static/home/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/overlay.png -------------------------------------------------------------------------------- /doc/_static/home/pandas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/pandas.gif -------------------------------------------------------------------------------- /doc/_static/home/plotly.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/plotly.gif -------------------------------------------------------------------------------- /doc/_static/home/widgets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/widgets.gif -------------------------------------------------------------------------------- /doc/_static/home/xarray.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/home/xarray.gif -------------------------------------------------------------------------------- /doc/_static/images/heat_and_trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/images/heat_and_trees.png -------------------------------------------------------------------------------- /doc/_static/images/portfolio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/images/portfolio.png -------------------------------------------------------------------------------- /doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/_static/logo.png -------------------------------------------------------------------------------- /doc/_static/patch_templates/sourcelink.html: -------------------------------------------------------------------------------- 1 | {# Added because of https://github.com/pydata/pydata-sphinx-theme/issues/2088 #} 2 | {# Displays a link to the .rst source of the current page. #} 3 | {% if show_source and has_source and sourcename %} 4 | 9 | {% endif %} 10 | -------------------------------------------------------------------------------- /doc/about.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | hvPlot is completely open source, available under a BSD license freely for both commercial and non-commercial use. hvPlot was originally developed with the support of [Anaconda Inc.](https://www.anaconda.com), and is now maintained by Anaconda developers and community contributors. 4 | 5 | hvPlot is part of the [HoloViz](https://holoviz.org) family of tools. The [holoviz.org](https://holoviz.org) website shows how to use hvPlot together with other libraries to solve complex problems, with detailed tutorials and examples. You can see a variety of projects using hvPlot at [examples.holoviz.org](https://examples.holoviz.org), and you can compare hvPlot to other available tools at [pyviz.org](https://pyviz.org). 6 | 7 | If you have any questions or usage issues visit the [hvPlot Discourse site](https://discourse.holoviz.org/c/hvplot). If you are interested in contributing to hvPlot development to help address some of the [open issues](https://github.com/holoviz/hvplot/issues), see our [developer instructions](https://hvplot.holoviz.org/developer_guide/index.html) to set up your development environment. 8 | 9 | If you like hvPlot and have built something you want to share, tweet a link or screenshot of your latest creation at @HoloViews, along with any other library you used (@HoloViz_org, @Datashader, @BokehPlots, @Matplotlib, etc.). Thanks! 10 | -------------------------------------------------------------------------------- /doc/assets/console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/assets/console.png -------------------------------------------------------------------------------- /doc/assets/console_server.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/assets/console_server.gif -------------------------------------------------------------------------------- /doc/assets/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/assets/diagram.png -------------------------------------------------------------------------------- /doc/assets/hvplot-wm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/assets/hvplot-wm.png -------------------------------------------------------------------------------- /doc/assets/streamz_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/doc/assets/streamz_demo.gif -------------------------------------------------------------------------------- /doc/conftest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from importlib.util import find_spec 4 | 5 | import dask 6 | 7 | from packaging.version import Version 8 | from bokeh.io.webdriver import webdriver_control 9 | 10 | 11 | collect_ignore_glob = [ 12 | 'user_guide/Streaming.ipynb', 13 | ] 14 | 15 | # On MacOs, Python 3.12 and 3.13, got the following error running this: 16 | # `pos = layout(G)` 17 | # => OSError: Format: "dot" not recognized. No formats found. 18 | # Fixed locally by running `dot -c` 19 | if not find_spec('pygraphviz') or ( 20 | sys.platform == 'darwin' and sys.version_info[:2] in [(3, 12), (3, 13)] 21 | ): 22 | collect_ignore_glob += [ 23 | 'user_guide/NetworkX.ipynb', 24 | ] 25 | 26 | if not find_spec('geoviews'): 27 | collect_ignore_glob += [ 28 | 'tutorials/getting_started.ipynb', 29 | 'reference/geopandas/*.ipynb', 30 | 'reference/xarray/contour.ipynb', 31 | 'reference/xarray/contourf.ipynb', 32 | 'reference/xarray/image.ipynb', 33 | 'reference/xarray/quadmesh.ipynb', 34 | 'reference/xarray/vectorfield.ipynb', 35 | 'user_guide/Explorer.ipynb', 36 | 'user_guide/Geographic_Data.ipynb', 37 | 'user_guide/Integrations.ipynb', 38 | ] 39 | 40 | # Gives weird solve on Python 3.9 41 | if not find_spec('ibis') or sys.version_info[:2] == (3, 9): 42 | collect_ignore_glob += [ 43 | 'ref/data_libraries.ipynb', 44 | ] 45 | 46 | try: 47 | webdriver_control.create() 48 | except RuntimeError: 49 | # hvplot.save() with bokeh 50 | collect_ignore_glob += [ 51 | 'user_guide/Viewing.ipynb', 52 | 'user_guide/NetworkX.ipynb', 53 | ] 54 | finally: 55 | webdriver_control.cleanup() 56 | 57 | 58 | if Version(dask.__version__).release < (2025, 1, 0): 59 | # From Dask 2024.3.0 they now use `dask_expr` by default 60 | # https://github.com/dask/dask/issues/10995 61 | dask.config.set({'dataframe.query-planning': False}) 62 | 63 | 64 | # https://github.com/pydata/xarray/pull/9182 65 | try: 66 | import xarray as xr 67 | except ImportError: 68 | pass 69 | else: 70 | import numpy as np 71 | 72 | if Version(np.__version__) >= Version('2.0.0') and Version(xr.__version__) <= Version( 73 | '2024.6.0' 74 | ): 75 | collect_ignore_glob += [ 76 | 'user_guide/Gridded_Data.ipynb', 77 | ] 78 | -------------------------------------------------------------------------------- /doc/governance/project-docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | For the contributing policy, see [HoloViz/HoloViz - CONTRIBUTING.md](https://github.com/holoviz/holoviz/blob/hvplot-gov/doc/governance/project-docs/CONTRIBUTING.md). 4 | 5 | The hvPlot Project’s equivalently named documents take precedence over any external materials referenced within this linked document above. 6 | -------------------------------------------------------------------------------- /doc/governance/project-docs/GOVERNANCE.md: -------------------------------------------------------------------------------- 1 | # Governance Policy 2 | 3 | 4 | The "Project" is herein defined as the activities related to this specific GitHub repository [`hvPlot`](https://github.com/holoviz/hvplot), within the `HoloViz` GitHub Organization. 5 | 6 | 7 | This Project adopts the governance specified by all of the numbered sections of [HoloViz/HoloViz - GOVERNANCE.md](https://github.com/holoviz/holoviz/blob/hvplot-gov/doc/governance/project-docs/GOVERNANCE.md). 8 | 9 | 10 | The hvPlot Project’s equivalently named documents take precedence over any external materials referenced within this linked document above. 11 | -------------------------------------------------------------------------------- /doc/governance/project-docs/LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | For the license, see [HoloViz/hvPlot - LICENSE.txt](https://github.com/holoviz/hvplot/blob/main/LICENSE). 4 | -------------------------------------------------------------------------------- /doc/governance/project-docs/MEMBERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | For member policy, see the description at the top of [HoloViz/HoloViz - MEMBERS.md](https://github.com/holoviz/holoviz/blob/hvplot-gov/doc/governance/project-docs/MEMBERS.md). 4 | 5 | 6 | The hvPlot Project’s equivalently named documents take precedence over any external materials referenced within this linked document above. 7 | 8 | 9 | | **NAME** | **Role** | **GitHub Handle** | 10 | | --- | --- | --- | 11 | | Philipp Rudiger | Project Director | [philippjfr](https://github.com/philippjfr) | 12 | | Maxime Liquet | Lead Maintainer | [maximlt](https://github.com/maximlt) | 13 | | Simon Høxbro Hansen | Maintainer | [hoxbro](https://github.com/hoxbro) | 14 | | Andrew Huang | Maintainer | [ahuang11](https://github.com/ahuang11) | 15 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.area.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# hvPlot.area" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "```{eval-rst}\n", 15 | ".. currentmodule:: hvplot\n", 16 | "\n", 17 | ".. automethod:: hvPlot.area\n", 18 | "```\n", 19 | "\n", 20 | "## Backend-specific styling options\n", 21 | "\n", 22 | "```{eval-rst}\n", 23 | ".. backend-styling-options:: area\n", 24 | "```\n", 25 | "\n", 26 | "## Examples \n", 27 | "\n", 28 | "TBD" 29 | ] 30 | } 31 | ], 32 | "metadata": { 33 | "language_info": { 34 | "name": "python", 35 | "pygments_lexer": "ipython3" 36 | } 37 | }, 38 | "nbformat": 4, 39 | "nbformat_minor": 4 40 | } 41 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.bar.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "5644213a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.bar\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.bar\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: bar\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.barh.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b5550786", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.barh\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.barh\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: barh\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.bivariate.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a287ab2a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.bivariate\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.bivariate\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: bivariate\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.box.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "67aa50a9", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.box\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.box\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: box\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.contour.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "5aa3941a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.contour\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.contour\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: contour\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.contourf.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b27350ca", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.contourf\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.contourf\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: contourf\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.dataset.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b27350ca", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.dataset\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.dataset\n", 14 | "```\n", 15 | "\n", 16 | "## Examples\n", 17 | "\n", 18 | "TBD" 19 | ] 20 | } 21 | ], 22 | "metadata": { 23 | "language_info": { 24 | "name": "python", 25 | "pygments_lexer": "ipython3" 26 | } 27 | }, 28 | "nbformat": 4, 29 | "nbformat_minor": 4 30 | } 31 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.density.md: -------------------------------------------------------------------------------- 1 | ## hvPlot.density 2 | 3 | `hvPlot.density` is an alias for {meth}`hvPlot.kde `. 4 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.errorbars.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "0ed32b5a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.errorbars\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.errorbars\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: errorbars\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.heatmap.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "8b1ed2e6", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.heatmap\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.heatmap\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: heatmap\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.hexbin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "bbc8492d", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.hexbin\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.hexbin\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: hexbin\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.hist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "0fdf6ca7", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.hist\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.hist\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: hist\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.image.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "e495a53c", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.image\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.image\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: image\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.kde.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "60504550", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.kde\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.kde\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: kde\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.labels.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "d4cb57f3", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.labels\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.labels\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: labels\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.line.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "0ff60267", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.line\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.line\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: line\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.ohlc.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3bc617e1", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.ohlc\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.ohlc\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: ohlc\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.paths.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a148906a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.paths\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.paths\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: paths\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 2 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.points.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "12c76e4e", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.points\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.points\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: points\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.polygons.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "59a8362e", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.polygons\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.polygons\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: polygons\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.quadmesh.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "223ae36d", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.quadmesh\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.quadmesh\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: quadmesh\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.rgb.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "c1283248", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.rgb\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.rgb\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: rgb\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.scatter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f99cff3c", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.scatter\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.scatter\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: scatter\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.step.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a4a2bf27", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.step\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.step\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: step\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.table.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "9fed5c11", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.table\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.table\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: table\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.vectorfield.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "37719ebd", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.vectorfield\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.vectorfield\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: vectorfield\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.hvPlot.violin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "092313dc", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvPlot.violin\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot\n", 12 | "\n", 13 | ".. automethod:: hvPlot.violin\n", 14 | "```\n", 15 | "\n", 16 | "## Backend-specific styling options\n", 17 | "\n", 18 | "```{eval-rst}\n", 19 | ".. backend-styling-options:: violin\n", 20 | "```\n", 21 | "\n", 22 | "## Examples\n", 23 | "\n", 24 | "TBD" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "language_info": { 30 | "name": "python", 31 | "pygments_lexer": "ipython3" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.plotting.andrews_curves.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "acb844e8", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvplot.plotting.andrews_curves\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot.plotting\n", 12 | "\n", 13 | ".. autofunction:: andrews_curves\n", 14 | "```\n", 15 | "\n", 16 | "## Examples\n", 17 | "\n", 18 | "TBD" 19 | ] 20 | } 21 | ], 22 | "metadata": { 23 | "language_info": { 24 | "name": "python", 25 | "pygments_lexer": "ipython3" 26 | } 27 | }, 28 | "nbformat": 4, 29 | "nbformat_minor": 5 30 | } 31 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.plotting.lag_plot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "2d7486a8", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvplot.plotting.lag_plot\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot.plotting\n", 12 | "\n", 13 | ".. autofunction:: lag_plot\n", 14 | "```\n", 15 | "\n", 16 | "## Examples\n", 17 | "\n", 18 | "TBD" 19 | ] 20 | } 21 | ], 22 | "metadata": { 23 | "language_info": { 24 | "name": "python", 25 | "pygments_lexer": "ipython3" 26 | } 27 | }, 28 | "nbformat": 4, 29 | "nbformat_minor": 5 30 | } 31 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.plotting.parallel_coordinates.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "fc23da68", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvplot.plotting.parallelcoordinates\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot.plotting\n", 12 | "\n", 13 | ".. autofunction:: parallel_coordinates\n", 14 | "```\n", 15 | "\n", 16 | "## Examples\n", 17 | "\n", 18 | "TBD" 19 | ] 20 | } 21 | ], 22 | "metadata": { 23 | "language_info": { 24 | "name": "python", 25 | "pygments_lexer": "ipython3" 26 | } 27 | }, 28 | "nbformat": 4, 29 | "nbformat_minor": 5 30 | } 31 | -------------------------------------------------------------------------------- /doc/ref/api/manual/hvplot.plotting.scatter_matrix.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "c807393a", 6 | "metadata": {}, 7 | "source": [ 8 | "# hvplot.plotting.scatter_matrix\n", 9 | "\n", 10 | "```{eval-rst}\n", 11 | ".. currentmodule:: hvplot.plotting\n", 12 | "\n", 13 | ".. autofunction:: scatter_matrix\n", 14 | "```\n", 15 | "\n", 16 | "## Examples\n", 17 | "\n", 18 | "TBD" 19 | ] 20 | } 21 | ], 22 | "metadata": { 23 | "language_info": { 24 | "name": "python", 25 | "pygments_lexer": "ipython3" 26 | } 27 | }, 28 | "nbformat": 4, 29 | "nbformat_minor": 5 30 | } 31 | -------------------------------------------------------------------------------- /doc/ref/api_compatibility/index.md: -------------------------------------------------------------------------------- 1 | # API compatibility 2 | 3 | This section aims to provide more precise information about the compatibility of hvPlot's plotting API with other libraries. 4 | 5 | ```{toctree} 6 | :titlesonly: 7 | :maxdepth: 2 8 | 9 | Pandas 10 | ``` 11 | -------------------------------------------------------------------------------- /doc/ref/deprecations.md: -------------------------------------------------------------------------------- 1 | # Deprecations and Removals 2 | 3 | List of currently deprecated APIs: 4 | 5 | | Warning | Description | 6 | |-|-| 7 | | `FutureWarning` since `0.12.0` | Passing DuckDB objects to `hvplot.plotting.plot`, use `import hvplot.duckdb` instead. | 8 | | `FutureWarning` since `0.12.0` | `debug` argument | 9 | 10 | List (created after the release of version `0.12.0`) of removed APIs: 11 | 12 | | Removed in | Warning | Description | 13 | |-|-|-| 14 | | | | | 15 | -------------------------------------------------------------------------------- /doc/ref/index.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | The reference section includes the API reference and pages that provide detailed information about hvPlot's usage. 4 | 5 | ```{toctree} 6 | :titlesonly: 7 | :includehidden: 8 | :maxdepth: 2 9 | 10 | Installation 11 | Supported data libraries 12 | Supported plotting extensions 13 | Plotting options 14 | API 15 | API compatibility 16 | Deprecations/Removals 17 | ``` 18 | -------------------------------------------------------------------------------- /doc/ref/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | This page lists the primary sources from which hvPlot can be installed. 4 | 5 | ## From PyPI 6 | 7 | hvPlot is distributed on [PyPI](https://pypi.org/project/hvplot/) as a wheel and as a source distribution (sdist). 8 | 9 | ::::{tab-set} 10 | 11 | :::{tab-item} pip 12 | 13 | ``` 14 | pip install hvplot 15 | ``` 16 | 17 | ::: 18 | 19 | :::{tab-item} uv 20 | 21 | ``` 22 | uv pip install hvplot 23 | ``` 24 | 25 | :::: 26 | 27 | Pre-releases (alpha, beta, release candidate) can also be installed from PyPI. 28 | 29 | ::::{tab-set} 30 | 31 | :::{tab-item} pip 32 | 33 | ``` 34 | pip install hvplot --pre 35 | ``` 36 | 37 | ::: 38 | 39 | :::{tab-item} uv 40 | 41 | ``` 42 | uv pip install hvplot --prerelease allow 43 | ``` 44 | 45 | :::: 46 | 47 | ## From anaconda.org 48 | 49 | hvPlot is distributed on 3 channels on [anaconda.org](https://anaconda.org/): 50 | 51 | - [`conda-forge`](https://github.com/conda-forge/hvplot-feedstock): Community maintained channel 52 | - [`defaults`](https://github.com/AnacondaRecipes/hvplot-feedstock/): Anaconda maintained channel (free under certain conditions only, check Anaconda's Terms of Services) 53 | - `pyviz`: HoloViz' custom channel 54 | 55 | We recommend installing final releases either from `conda-forge` or `defaults`. Pre-releases are only available from the `pyviz/label/dev` subchannel. 56 | 57 | hvPlot can be installed from these channels using [conda](https://docs.conda.io), [pixi](https://pixi.sh), [mamba/micromamba](https://mamba.readthedocs.io), etc. 58 | 59 | ::::{tab-set} 60 | 61 | :::{tab-item} `conda-forge` 62 | 63 | ``` 64 | conda install conda-forge::hvplot 65 | ``` 66 | 67 | ::: 68 | 69 | :::{tab-item} `defaults` 70 | 71 | ``` 72 | conda install defaults::hvplot 73 | ``` 74 | 75 | ::: 76 | 77 | :::{tab-item} Pre-releases from `pyviz/label/dev` 78 | 79 | ``` 80 | conda install pyviz/label/dev::hvplot 81 | ``` 82 | 83 | ::: 84 | 85 | :::: 86 | 87 | ## From Anaconda Distribution 88 | 89 | If you just started with Python and programming in general, an easy way to install hvPlot on your computer is to download and install the [Anaconda Distribution](https://www.anaconda.com/download) that includes most of the HoloViz packages. Note it is subject to Anaconda's Terms of Services. 90 | 91 | ## From source 92 | 93 | hvPlot can be installed from source by cloning its [GitHub repository](https://github.com/holoviz/hvplot) and running this command: 94 | 95 | ``` 96 | pip install -e . 97 | ``` 98 | -------------------------------------------------------------------------------- /doc/ref/plotting_extensions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Supported plotting extensions\n", 8 | "\n", 9 | "hvPlot supports generating plots with 3 different plotting extensions. Under the hood, hvPlot delegates plotting to HoloViews which itself calls these plotting libraries.\n", 10 | "\n", 11 | "The following below provides a summary of the supported plotting extensions. In the *HoloViews support* column you will find an estimate of how well the extension is supported in HoloViews, and consequently in hvPlot:\n", 12 | "\n", 13 | "- Bokeh has become the de-facto default plotting extension across HoloViz and is the most used and tested one.\n", 14 | "- Matplotlib was originally the unique plotting extension of HoloViews and is still well supported. Being a static plotting library, the extension doesn't benefit from all the interactive features HoloViews can offer (hover, streams, etc.).\n", 15 | "- Plotly is another interactive plotting extension supported by HoloViews, and while it enables some unique features (e.g. 3D plots), it is not as well supported as its counterpart Bokeh.\n", 16 | "\n", 17 | "| Plotting extension | Type | HoloViews support |\n", 18 | "| ---------------------------------- | ----------- | ----------------- |\n", 19 | "| [Bokeh](#plot-ext-bokeh) | Interactive | ⭐⭐⭐ |\n", 20 | "| [Matplotlib](#plot-ext-matplotlib) | Static | ⭐⭐ |\n", 21 | "| [Plotly](#plot-ext-plotly) | Interactive | ⭐ |\n", 22 | "\n", 23 | "Follow the [Plotting Extensions Guide](../user_guide/Plotting_Extensions.ipynb) for more information.\n", 24 | "\n", 25 | ":::{note}\n", 26 | "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", 27 | ":::" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "(plot-ext-bokeh)=\n", 35 | "## Bokeh (default)\n", 36 | "\n", 37 | "TBD" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "(plot-ext-matplotlib)=\n", 45 | "## Matplotlib\n", 46 | "\n", 47 | "TBD" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "(plot-ext-plotly)=\n", 55 | "## Plotly\n", 56 | "\n", 57 | "TBD" 58 | ] 59 | } 60 | ], 61 | "metadata": { 62 | "language_info": { 63 | "name": "python", 64 | "pygments_lexer": "ipython3" 65 | } 66 | }, 67 | "nbformat": 4, 68 | "nbformat_minor": 2 69 | } 70 | -------------------------------------------------------------------------------- /doc/reference/geopandas/points.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Points" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Using hvplot with geopandas is as simple as loading a geopandas dataframe and calling `hvplot` on it with `geo=True`." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import geopandas as gpd\n", 33 | "\n", 34 | "\n", 35 | "data = {\n", 36 | " 'City': ['London', 'Paris', 'Berlin', 'Madrid', 'Rome', 'Vienna', 'Warsaw', 'Amsterdam'],\n", 37 | " 'Country': ['United Kingdom', 'France', 'Germany', 'Spain', 'Italy', 'Austria', 'Poland', 'Netherlands'],\n", 38 | " 'Latitude': [51.5074, 48.8566, 52.5200, 40.4168, 41.9028, 48.2082, 52.2297, 52.3676],\n", 39 | " 'Longitude': [-0.1278, 2.3522, 13.4050, -3.7038, 12.4964, 16.3738, 21.0122, 4.9041]\n", 40 | "}\n", 41 | "cities = gpd.GeoDataFrame(\n", 42 | " data,\n", 43 | " geometry=gpd.points_from_xy(data['Longitude'], data['Latitude']),\n", 44 | " crs=\"EPSG:4326\",\n", 45 | ")" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "cities.hvplot(geo=True, tiles=True)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "You can easily change the tiles, add coastlines, or which fields show up in the hover text:" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "cities.hvplot(tiles='EsriTerrain', coastline=True, hover_cols='all')" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "We can also alter the projection of the data using cartopy:" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "import cartopy.crs as ccrs" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "cities.hvplot(coastline=True, projection=ccrs.Geostationary(central_longitude=10), global_extent=True)" 96 | ] 97 | } 98 | ], 99 | "metadata": { 100 | "language_info": { 101 | "name": "python", 102 | "pygments_lexer": "ipython3" 103 | } 104 | }, 105 | "nbformat": 4, 106 | "nbformat_minor": 4 107 | } 108 | -------------------------------------------------------------------------------- /doc/reference/geopandas/polygons.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Polygons" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Using hvplot with geopandas is as simple as loading a geopandas dataframe and calling `hvplot` on it with `geo=True`." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import geodatasets\n", 33 | "import geopandas as gpd\n", 34 | "\n", 35 | "chicago = gpd.read_file(geodatasets.get_path(\"geoda.chicago_commpop\"))\n", 36 | "chicago.sample(3)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "chicago.hvplot(geo=True)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "Control the color of the elements using the `c` option." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "chicago.hvplot.polygons(geo=True, c='POP2010', hover_cols='all')" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "You can even color by another series, such as population density:" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "chicago.hvplot.polygons(\n", 78 | " geo=True,\n", 79 | " c=chicago.POP2010/chicago.to_crs('EPSG:32616').area,\n", 80 | " clabel='pop density',\n", 81 | ")" 82 | ] 83 | } 84 | ], 85 | "metadata": { 86 | "language_info": { 87 | "name": "python", 88 | "pygments_lexer": "ipython3" 89 | } 90 | }, 91 | "nbformat": 4, 92 | "nbformat_minor": 4 93 | } 94 | -------------------------------------------------------------------------------- /doc/reference/tabular/andrewscurves.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "285a3796-e7d9-45ba-8b11-418c0535a8c9", 6 | "metadata": {}, 7 | "source": [ 8 | "# Andrewscurves" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "d8d7bf92-ae63-4122-9457-10c9ada6c6f1", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.pandas # noqa" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "id": "915da73a-0a5f-4a40-aa4b-a65a6002c3e9", 24 | "metadata": {}, 25 | "source": [ 26 | "Andrews curves provides a mechanism for visualising clusters of multivariate data.\n", 27 | "\n", 28 | "Andrews curves have the functional form:\n", 29 | "\n", 30 | " f(t) = x_1/sqrt(2) + x_2 sin(t) + x_3 cos(t) + x_4 sin(2t) + x_5 cos(2t) + ...\n", 31 | "\n", 32 | "Where *x* coefficients correspond to the values of each dimension and *t* is\n", 33 | "linearly spaced between *-pi* and *+pi*. Each row of frame then corresponds to\n", 34 | "a single curve." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "id": "d85a9c83-bd5d-4ac2-b1a0-0bb451a484e9", 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "from bokeh.sampledata import iris\n", 45 | "\n", 46 | "iris = iris.flowers" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "id": "780fc986-819b-4882-9c44-113b9a211d97", 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "iris.head()" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "id": "4c721441-ecf3-4178-a55f-d43eed7d00a5", 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "hvplot.plotting.andrews_curves(\n", 67 | " iris,\n", 68 | " class_column='species',\n", 69 | " samples=20,\n", 70 | ")" 71 | ] 72 | } 73 | ], 74 | "metadata": { 75 | "language_info": { 76 | "name": "python", 77 | "pygments_lexer": "ipython3" 78 | } 79 | }, 80 | "nbformat": 4, 81 | "nbformat_minor": 5 82 | } 83 | -------------------------------------------------------------------------------- /doc/reference/tabular/area.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Area" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`area` can be used to color the area under a line or to color the space between two lines. " 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.degrees import data\n", 33 | "\n", 34 | "data.tail()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "First we'll look at a single curve, where we are enforcing the y axis must be between 0 and 100 and we set the background color." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "data.hvplot.area(\n", 51 | " x='Year', y='Computer Science',\n", 52 | " label='% of Computer Science Degrees Earned by Women',\n", 53 | " ylim=(0, 100), width=500, height=400, bgcolor='goldenrod',\n", 54 | ")" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "import pandas as pd\n", 64 | "from bokeh.sampledata.stocks import MSFT\n", 65 | "\n", 66 | "df = pd.DataFrame(MSFT)\n", 67 | "df['date'] = pd.to_datetime(df.date)\n", 68 | "df.head()" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "To color the area between two curves, include both a `y` and a `y2`." 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [ 84 | "df[df.date.dt.year == 2000].hvplot.area(x='date', y='low', y2='high')" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "When multiple y values are passed, they are stacked by default." 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "df.hvplot.area(x='date', y=['open', 'close'])" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "Area plots can also be unstacked:" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "df.hvplot.area(x='date', y=['open', 'close'], stacked=False,\n", 117 | " groupby='date.year', legend='bottom_right', width=500)" 118 | ] 119 | } 120 | ], 121 | "metadata": { 122 | "language_info": { 123 | "name": "python", 124 | "pygments_lexer": "ipython3" 125 | } 126 | }, 127 | "nbformat": 4, 128 | "nbformat_minor": 4 129 | } 130 | -------------------------------------------------------------------------------- /doc/reference/tabular/barh.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Barh" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`barh()` is similar to `.bar()` but plots bars horizontally rather than vertically. These charts can be created from dataframes with regular `Index` or `MultiIndex`." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.autompg import autompg_clean as df\n", 33 | "\n", 34 | "table = df.groupby(['origin', 'mfr'])['mpg'].mean().sort_values()\n", 35 | "table.head()" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "table.hvplot.barh('mfr', 'mpg', by='origin', stacked=True, legend='bottom_right', height=600)" 45 | ] 46 | } 47 | ], 48 | "metadata": { 49 | "language_info": { 50 | "name": "python", 51 | "pygments_lexer": "ipython3" 52 | } 53 | }, 54 | "nbformat": 4, 55 | "nbformat_minor": 4 56 | } 57 | -------------------------------------------------------------------------------- /doc/reference/tabular/bivariate.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Bivariate" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`bivariate()` is a statistical method for creating a 2D density plot. Bivariate plots can be a useful alternative to scatter plots if your data are too dense to plot each point individually." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.autompg import autompg_clean as df\n", 33 | "\n", 34 | "df.head()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "df.hvplot.bivariate('accel', 'mpg')" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "language_info": { 49 | "name": "python", 50 | "pygments_lexer": "ipython3" 51 | } 52 | }, 53 | "nbformat": 4, 54 | "nbformat_minor": 4 55 | } 56 | -------------------------------------------------------------------------------- /doc/reference/tabular/box.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Box" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`box` plots are most useful when grouped by additional dimensions." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.sprint import sprint as df\n", 33 | "\n", 34 | "df.head()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "boxplot = df.hvplot.box(y='Time', by='Medal', height=400, width=400, legend=False)\n", 44 | "boxplot" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "Overlay this plot with the jittered scatter plot of the medalist times using the `*` operator:" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "boxplot * df.hvplot.scatter(y='Time', x='Medal', c='orange').opts(jitter=0.5)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "Use `groupby` to create a separate plot for each medal type with a widget for selecting between the plots." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "df.hvplot.box(y='Time', groupby='Medal', by='Country', ylabel='Sprint Time', height=400, width=600)" 77 | ] 78 | } 79 | ], 80 | "metadata": { 81 | "language_info": { 82 | "name": "python", 83 | "pygments_lexer": "ipython3" 84 | } 85 | }, 86 | "nbformat": 4, 87 | "nbformat_minor": 4 88 | } 89 | -------------------------------------------------------------------------------- /doc/reference/tabular/errorbars.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Errorbars" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`errorbars` are most helpful when overlaid with other plot types. To do this we'll use the `*` operator." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata import perceptions\n", 33 | "\n", 34 | "data = perceptions.numberly.describe().transpose().sort_values('mean')\n", 35 | "data" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "First we'll use just one column to set the size of the errorbars around 'mean'." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "data.hvplot.scatter(y='mean', ylabel='amount') * data.hvplot.errorbars(y='mean', yerr1='std')" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "Then we'll use two columns. Remember that these are not the absolute placements of the ends of the bars, but the distance from the center." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "data['yerr1'] = data['mean'] - data['min']\n", 68 | "data['yerr2'] = data['max'] - data['mean']\n", 69 | "data.hvplot.scatter(y='mean', ylabel='amount') * data.hvplot.errorbars(y='mean', yerr1='yerr1', yerr2='yerr2')" 70 | ] 71 | } 72 | ], 73 | "metadata": { 74 | "language_info": { 75 | "name": "python", 76 | "pygments_lexer": "ipython3" 77 | } 78 | }, 79 | "nbformat": 4, 80 | "nbformat_minor": 4 81 | } 82 | -------------------------------------------------------------------------------- /doc/reference/tabular/heatmap.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Heatmap" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`heatmap` can be data has two categorical axes. Data can either be pre-computed into a matrix, or it can be 1d and the aggregation will be computed when rendering." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata import sea_surface_temperature as sst\n", 33 | "\n", 34 | "df = sst.sea_surface_temperature\n", 35 | "df.tail()" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "In the first example, we'll make a sea surface temperature calendar of sorts:" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "df.hvplot.heatmap(x='time.month', y='time.day', C='temperature', \n", 52 | " height=500, width=500, colorbar=False)" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "If the value for each section of the heatmap is pre-computed, then use `x='index'` and `y='columns'` to plot those values. Note to see how to make this same plot in bokeh, see the [bokeh docs](https://docs.bokeh.org/en/latest/docs/user_guide/topics/categorical.html#categorical-heatmaps)." 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "from bokeh.sampledata.unemployment1948 import data\n", 69 | "\n", 70 | "data = data.set_index('Year').drop('Annual', axis=1).transpose()\n", 71 | "data.head()" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "data.hvplot.heatmap(\n", 81 | " x='columns', \n", 82 | " y='index', \n", 83 | " title='US Unemployment 1948—2016', \n", 84 | " cmap=[\"#75968f\", \"#a5bab7\", \"#c9d9d3\", \"#e2e2e2\", \"#dfccce\", \"#ddb7b1\", \"#cc7878\", \"#933b41\", \"#550b1d\"], \n", 85 | " xaxis='top', \n", 86 | " rot=70,\n", 87 | " width=800, height=300).opts(\n", 88 | " toolbar=None, \n", 89 | " fontsize={'title': 10, 'xticks': 5, 'yticks': 5}\n", 90 | ")" 91 | ] 92 | } 93 | ], 94 | "metadata": { 95 | "language_info": { 96 | "name": "python", 97 | "pygments_lexer": "ipython3" 98 | } 99 | }, 100 | "nbformat": 4, 101 | "nbformat_minor": 4 102 | } 103 | -------------------------------------------------------------------------------- /doc/reference/tabular/hexbin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hexbin" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`.hexbin()` offers a straightforward method for plotting dense data." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import pandas as pd\n", 33 | "from bokeh.sampledata.stocks import AAPL\n", 34 | "\n", 35 | "df = pd.DataFrame(AAPL)\n", 36 | "df.head()" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "df.hvplot.hexbin('open', 'volume', logz=True, clabel='Count',\n", 46 | " height=400, width=500)" 47 | ] 48 | } 49 | ], 50 | "metadata": { 51 | "language_info": { 52 | "name": "python", 53 | "pygments_lexer": "ipython3" 54 | } 55 | }, 56 | "nbformat": 4, 57 | "nbformat_minor": 4 58 | } 59 | -------------------------------------------------------------------------------- /doc/reference/tabular/hist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hist" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa\n", 17 | "\n", 18 | "# hvplot.extension(\"matplotlib\")" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "`hist` is often a good way to start looking at continuous data to get a sense of the distribution. Similar methods include [`kde`](kde.ipynb) (also available as `density`)." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "from bokeh.sampledata.autompg import autompg_clean\n", 35 | "\n", 36 | "autompg_clean.sample(n=5)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "autompg_clean.hvplot.hist(\"weight\")" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "When using `by` the plots are overlaid by default. To create subplots instead, use `subplots=True`." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "autompg_clean.hvplot.hist(\"weight\", by=\"origin\", subplots=True, width=250)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "You can also plot histograms of *datetime* data" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "import pandas as pd\n", 78 | "from bokeh.sampledata.commits import data as commits\n", 79 | "\n", 80 | "commits = commits.reset_index().sort_values(\"datetime\")\n", 81 | "commits.head(3)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "commits.hvplot.hist(\n", 91 | " \"datetime\",\n", 92 | " bin_range=(pd.Timestamp('2012-11-30'), pd.Timestamp('2017-05-01')),\n", 93 | " bins=54, \n", 94 | ")" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "If you want to plot the distribution of a categorical column you can calculate the distribution using Pandas' method `value_counts` and plot it using `.hvplot.bar`." 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "autompg_clean[\"mfr\"].value_counts().hvplot.bar(invert=True, flip_yaxis=True, height=500)" 111 | ] 112 | } 113 | ], 114 | "metadata": { 115 | "language_info": { 116 | "name": "python", 117 | "pygments_lexer": "ipython3" 118 | } 119 | }, 120 | "nbformat": 4, 121 | "nbformat_minor": 4 122 | } 123 | -------------------------------------------------------------------------------- /doc/reference/tabular/kde.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Kde" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Kernel density estimate (`kde`) provides a mechanism for showing the distribution and spread of the data. In `hvplot` the method is exposed both as `kde` and `density`." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata import sea_surface_temperature as sst\n", 33 | "\n", 34 | "df = sst.sea_surface_temperature\n", 35 | "df.tail()" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "df.hvplot.kde()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "There are many options exposed and explorable using tab completion. In this case we'll create a colormap that spans the rainbow and divide the temperature by month." 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "import numpy as np\n", 61 | "import colorcet as cc" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "categorical_cmap = [cc.rainbow[int(i)] for i in np.linspace(0, 255, 12)]" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "df.hvplot.kde(by='time.month', cmap=categorical_cmap, legend='top', height=400)" 80 | ] 81 | } 82 | ], 83 | "metadata": { 84 | "language_info": { 85 | "name": "python", 86 | "pygments_lexer": "ipython3" 87 | } 88 | }, 89 | "nbformat": 4, 90 | "nbformat_minor": 4 91 | } 92 | -------------------------------------------------------------------------------- /doc/reference/tabular/labels.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Labels" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`labels` are mostly useful when overlaid on top of other plots. For instance in this case we will plot some capitals as points and then overlay (using the `*` operator) labels." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import pandas as pd\n", 33 | "\n", 34 | "df = pd.DataFrame(\n", 35 | " {'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas'],\n", 36 | " 'Country': ['Argentina', 'Brazil', 'Chile', 'Colombia', 'Venezuela'],\n", 37 | " 'Latitude': [-34.58, -15.78, -33.45, 4.60, 10.48],\n", 38 | " 'Longitude': [-58.66, -47.91, -70.66, -74.08, -66.86]})\n", 39 | "df" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "df.hvplot.points(x='Longitude', y='Latitude', padding=0.2, hover_cols='all', width=300) * \\\n", 49 | "df.hvplot.labels(x='Longitude', y='Latitude', text='City', text_baseline='bottom', hover=False) * \\\n", 50 | "df.hvplot.labels(x='Longitude', y='Latitude', text='Country', text_baseline='top', hover=False)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "It's also possible to provide a template string containing the names of the columns and reduce the font size." 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "df.hvplot.points(x='Longitude', y='Latitude', padding=0.2, hover_cols='all', width=300) * \\\n", 67 | "df.hvplot.labels(x='Longitude', y='Latitude', text='@{City}, {Country}', text_baseline='bottom', text_font_size='10px', hover=False)" 68 | ] 69 | } 70 | ], 71 | "metadata": { 72 | "language_info": { 73 | "name": "python", 74 | "pygments_lexer": "ipython3" 75 | } 76 | }, 77 | "nbformat": 4, 78 | "nbformat_minor": 4 79 | } 80 | -------------------------------------------------------------------------------- /doc/reference/tabular/lagplot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "7eb37c52-8262-4359-a6c1-3214e675fa5d", 6 | "metadata": {}, 7 | "source": [ 8 | "# Lagplot" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "cb5dd3db-78c4-4a01-ba07-37f718f7425a", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.pandas # noqa\n", 19 | "import numpy as np\n", 20 | "import pandas as pd" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "id": "c7af165e-4231-49ea-81d7-d07ad81a05da", 26 | "metadata": {}, 27 | "source": [ 28 | "Lag plots are most commonly used to look for patterns in time series data." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "815a51ab-5f61-4bea-bb56-e11a0f117718", 34 | "metadata": {}, 35 | "source": [ 36 | "Given the following time series:" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "id": "283adbd9-3c42-4cb7-8c57-1d0e9fe1d25f", 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "np.random.seed(5)\n", 47 | "x = np.cumsum(np.random.normal(loc=1, scale=5, size=50))\n", 48 | "s = pd.Series(x, name='Time series')\n", 49 | "\n", 50 | "s.hvplot()" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "id": "8a877a7d-11cb-4bcb-81e4-3936f061ba65", 56 | "metadata": {}, 57 | "source": [ 58 | "A lag plot with `lag=1` returns:" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "id": "52be318e-fccd-461d-9813-c231b6f2997c", 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "hvplot.plotting.lag_plot(s, lag=1)" 69 | ] 70 | } 71 | ], 72 | "metadata": { 73 | "language_info": { 74 | "name": "python", 75 | "pygments_lexer": "ipython3" 76 | } 77 | }, 78 | "nbformat": 4, 79 | "nbformat_minor": 5 80 | } 81 | -------------------------------------------------------------------------------- /doc/reference/tabular/line.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Line" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`line` is useful when data is continuous and has a continuous axis." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.degrees import data as deg\n", 33 | "deg.head()" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "deg.hvplot.line(x='Year', y=['Art and Performance', 'Business', 'Biology', 'Education', 'Computer Science'], \n", 43 | " value_label='% of Degrees Earned by Women', legend='top', height=500, width=620)" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "language_info": { 49 | "name": "python", 50 | "pygments_lexer": "ipython3" 51 | } 52 | }, 53 | "nbformat": 4, 54 | "nbformat_minor": 4 55 | } 56 | -------------------------------------------------------------------------------- /doc/reference/tabular/ohlc.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Ohlc" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import pandas as pd\n", 17 | "import hvplot.pandas # noqa" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "`ohlc` is a useful chart type to visualize stock movements" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "from bokeh.sampledata import stocks\n", 34 | "\n", 35 | "df = pd.DataFrame(stocks.AAPL)\n", 36 | "df['date'] = pd.to_datetime(df.date)\n", 37 | "\n", 38 | "df.iloc[-50:].hvplot.ohlc(grid=True)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "We can control the `neg_color`, `pos_color`, `line_color` and `bar_width`:" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "df.iloc[-50:].hvplot.ohlc(neg_color='indianred', pos_color='chartreuse', line_color='gray', bar_width=0.9, grid=True)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "By default `ohlc` will assume the `index` OR the first datetime column should be mapped to the x-axis and the first four non-datetime columns correspond to the O (open), H (high), L (low) and C (close) components. The default call is therefore equivalent to:" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "df.iloc[-50:].hvplot.ohlc('date', ['open', 'low', 'high', 'close'], grid=True)" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "Using the HoloViews `RangeToolLink` we can make it easy to scroll through the data while still seeing an overview of the overall timeseries:" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "from holoviews.plotting.links import RangeToolLink\n", 87 | "\n", 88 | "df_2012 = df[df.date > pd.to_datetime('2012')]\n", 89 | "\n", 90 | "ohlc = df_2012.hvplot.ohlc(ylabel='Price ($)', grid=True, xaxis=None)\n", 91 | "overview = df_2012.hvplot.ohlc(yaxis=None, height=150, fields={'date': 'Date'})\n", 92 | "volume = df_2012.hvplot.step('date', 'volume', height=100, xaxis=None)\n", 93 | "\n", 94 | "RangeToolLink(overview.get(0), ohlc.get(0))\n", 95 | "\n", 96 | "layout = (volume + ohlc + overview).cols(1)\n", 97 | "\n", 98 | "layout.opts(merge_tools=False)" 99 | ] 100 | } 101 | ], 102 | "metadata": { 103 | "language_info": { 104 | "name": "python", 105 | "pygments_lexer": "ipython3" 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 4 110 | } 111 | -------------------------------------------------------------------------------- /doc/reference/tabular/parallelcoordinates.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "fe36abdf-7ad3-4acf-8143-b8e9eb04c9a9", 6 | "metadata": {}, 7 | "source": [ 8 | "# Parallelcoordinates" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "98539b4c-af81-4ad7-9fe5-8e1b828ee3d8", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.pandas # noqa" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "id": "0b7674d1-b972-4b43-9e96-18c0d0fcc125", 24 | "metadata": {}, 25 | "source": [ 26 | "Parallel coordinates are a common way of visualizing and analyzing high-dimensional datasets.\n", 27 | "\n", 28 | "To show a set of points in an n-dimensional space, a backdrop is drawn consisting of n parallel lines, typically vertical and equally spaced. A point in n-dimensional space is represented as a polyline with vertices on the parallel axes; the position of the vertex on the i-th axis corresponds to the i-th coordinate of the point. " 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "id": "b524875d-aaa6-40da-8b1a-9f42f636da6a", 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "from bokeh.sampledata import iris\n", 39 | "\n", 40 | "iris = iris.flowers" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "id": "02fa9997-0c52-4ee8-890f-9ce2a6352e3f", 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "iris.head()" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "id": "c737ec55-2c45-40dd-92d0-69464607bf7f", 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "hvplot.plotting.parallel_coordinates(\n", 61 | " iris,\n", 62 | " class_column='species',\n", 63 | " cols=['sepal_length', 'petal_length', 'petal_width']\n", 64 | ")" 65 | ] 66 | } 67 | ], 68 | "metadata": { 69 | "language_info": { 70 | "name": "python", 71 | "pygments_lexer": "ipython3" 72 | } 73 | }, 74 | "nbformat": 4, 75 | "nbformat_minor": 5 76 | } 77 | -------------------------------------------------------------------------------- /doc/reference/tabular/paths.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Paths" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import pandas as pd\n", 17 | "import hvplot.pandas # noqa\n", 18 | "import cartopy.crs as ccrs" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "Paths are useful if you are plotting lines on a geographic map." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "df = pd.DataFrame({\"city\": [\"NY\", \"Delhi\"], \"lon\": [-75, 77.23], \"lat\": [43, 28.61]})" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Notice how the line in blue between New York and Delhi is not straight on a flat PlateCarree map, this is because the Geodetic coordinate system is a truly spherical coordinate system, where a line between two points is defined as the shortest path between those points on the globe rather than 2d Cartesian space." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "common_kwargs = dict(\n", 51 | " x=\"lon\",\n", 52 | " y=\"lat\",\n", 53 | " geo=True,\n", 54 | " project=True,\n", 55 | " projection=ccrs.GOOGLE_MERCATOR,\n", 56 | " global_extent=True\n", 57 | ")\n", 58 | "shortest_path = df.hvplot.paths(color=\"blue\", crs=ccrs.Geodetic(), tiles=True, **common_kwargs)\n", 59 | "straight_path = df.hvplot.paths(color=\"grey\", line_dash=\"dashed\", **common_kwargs)\n", 60 | "labels = df.hvplot.labels(text_color=\"black\", text=\"city\", **common_kwargs)\n", 61 | "shortest_path * straight_path * labels" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "Example adapted from https://scitools.org.uk/cartopy/docs/latest/matplotlib/intro.html." 69 | ] 70 | } 71 | ], 72 | "metadata": { 73 | "language_info": { 74 | "name": "python", 75 | "pygments_lexer": "ipython3" 76 | } 77 | }, 78 | "nbformat": 4, 79 | "nbformat_minor": 2 80 | } 81 | -------------------------------------------------------------------------------- /doc/reference/tabular/scatter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Scatter" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`scatter` plots are a good first way to plot data with non continuous axes." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.iris import flowers as df\n", 33 | "\n", 34 | "df.sample(n=5)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "df.hvplot.scatter(x='sepal_length', y='sepal_width', by='species', \n", 44 | " legend='top', height=400, width=400)" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "As for most other types of hvPlot plots, you can add fields to the hover display using the `hover_cols` argument. It can also take \"all\" as input to show all fields. " 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "df.hvplot.scatter(x='sepal_length', y='sepal_width', s='petal_length', scale=5, by='species', \n", 61 | " legend='top', height=400, width=600,\n", 62 | " hover_cols=[\"species\", \"sepal_length\", \"sepal_width\", \"petal_width\"])" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "You can add the 's' parameter in scatter to specify the marker plot size and add the 'scale' parameter to specify what the scaling factor should be." 70 | ] 71 | } 72 | ], 73 | "metadata": { 74 | "language_info": { 75 | "name": "python", 76 | "pygments_lexer": "ipython3" 77 | } 78 | }, 79 | "nbformat": 4, 80 | "nbformat_minor": 4 81 | } 82 | -------------------------------------------------------------------------------- /doc/reference/tabular/step.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Step" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`step` can be used pretty much anytime line might be used and has many of the same options available. " 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.degrees import data as deg\n", 33 | "deg.sample(n=5)" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "deg.hvplot.step(x='Year', y=['Art and Performance', 'Business', 'Biology', 'Education', 'Computer Science'], \n", 43 | " value_label='% of Degrees Earned by Women', legend='top', height=500, width=620)" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "language_info": { 49 | "name": "python", 50 | "pygments_lexer": "ipython3" 51 | } 52 | }, 53 | "nbformat": 4, 54 | "nbformat_minor": 4 55 | } 56 | -------------------------------------------------------------------------------- /doc/reference/tabular/table.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Table" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`table` allows the creation of a holoviews `Table` element with all the options available on that. It can be very useful especially when paired with other visualizations. " 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.autompg import autompg_clean as df\n", 33 | "\n", 34 | "df.head()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "df.hvplot.table(columns=['origin', 'name', 'yr'], sortable=True, selectable=True)" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "Click on the header to sort on the values in a column and on a row to select that column." 51 | ] 52 | } 53 | ], 54 | "metadata": { 55 | "language_info": { 56 | "name": "python", 57 | "pygments_lexer": "ipython3" 58 | } 59 | }, 60 | "nbformat": 4, 61 | "nbformat_minor": 4 62 | } 63 | -------------------------------------------------------------------------------- /doc/reference/tabular/violin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Violin" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.pandas # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`violin` plots are similar to box plots, but provide a better sense of the distribution of data. Note that `violin` plots depend on the `scipy` library." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from bokeh.sampledata.sprint import sprint as df\n", 33 | "\n", 34 | "df.head()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "df.hvplot.violin(y='Time', by='Medal', c='Medal', ylabel='Sprint Time',\n", 44 | " cmap=['gold', 'silver', 'brown'], legend=False, \n", 45 | " width=500, height=500, padding=0.4)" 46 | ] 47 | } 48 | ], 49 | "metadata": { 50 | "language_info": { 51 | "name": "python", 52 | "pygments_lexer": "ipython3" 53 | } 54 | }, 55 | "nbformat": 4, 56 | "nbformat_minor": 4 57 | } 58 | -------------------------------------------------------------------------------- /doc/reference/xarray/bar.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3b507dd1-31f6-4732-bbc7-c82f2135fe1f", 6 | "metadata": {}, 7 | "source": [ 8 | "# Bar" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "5d0ed0f8-ce26-4c54-9161-d34ca73ae716", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.xarray # noqa\n", 19 | "import xarray as xr" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "e3f7e297-9576-4c36-9a9f-a4200ccf2d36", 25 | "metadata": {}, 26 | "source": [ 27 | "## Introduction\n", 28 | "\n", 29 | "A `bar` plot represents **categorical data** with rectangular bars with heights proportional to the **numerical values** that they represent.\n", 30 | "The x-axis represents the categories and the y axis represents the numerical value scale.\n", 31 | "The bars are of equal width which allows for instant comparison of data." 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "id": "af429bbb-9a65-4b5d-b447-ce50b35dfedc", 37 | "metadata": {}, 38 | "source": [ 39 | "## Data\n", 40 | "\n", 41 | "Let's load some data." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "id": "8db8fff7-b85f-49ea-b281-4a4d86e0f3ee", 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "ds = xr.tutorial.open_dataset('air_temperature').load()\n", 52 | "air = ds.air\n", 53 | "air1d = air.sel(lon=285.,lat=40.).groupby('time.month').mean()\n", 54 | "air1d" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "id": "629c5172-9cba-4f5f-bf3b-67e0a390385b", 60 | "metadata": {}, 61 | "source": [ 62 | "## Basic Bar Plots" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "id": "dfd1afa2-e310-4630-bd30-96e390078caf", 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "air1d.hvplot.bar(y='air', height=500, title=\"Air Temperature by Month\")" 73 | ] 74 | } 75 | ], 76 | "metadata": { 77 | "language_info": { 78 | "name": "python", 79 | "pygments_lexer": "ipython3" 80 | } 81 | }, 82 | "nbformat": 4, 83 | "nbformat_minor": 5 84 | } 85 | -------------------------------------------------------------------------------- /doc/reference/xarray/contour.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Contour" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Similar to [`image`](image.ipynb), `contour` displays values on a 2d grid. But it first segments data into various levels." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import xarray as xr\n", 33 | "\n", 34 | "ds = xr.tutorial.open_dataset('air_temperature')\n", 35 | "ds" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "ds.hvplot.contour()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "There are lots of options exposed to control the style and contents of the `contour` plot:" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "ds.mean(dim='time').hvplot.contour(z='air', x='lon', y='lat', levels=20, \n", 61 | " clabel='T [K]', label='Mean Air temperature [K]',\n", 62 | " cmap='gray')" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "## Geographic Data\n", 70 | "\n", 71 | "Include a basemap from a tiling service using the `tiles` option." 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "ds.hvplot.contour(geo=True, tiles='EsriImagery', levels=20, line_width=2, cmap='reds',)" 81 | ] 82 | } 83 | ], 84 | "metadata": { 85 | "language_info": { 86 | "name": "python", 87 | "pygments_lexer": "ipython3" 88 | } 89 | }, 90 | "nbformat": 4, 91 | "nbformat_minor": 4 92 | } 93 | -------------------------------------------------------------------------------- /doc/reference/xarray/contourf.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Contourf" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Similar to [`image`](image.ipynb), `contourf` displays values on a 2d grid. But it first segments data into various levels." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "import xarray as xr\n", 33 | "\n", 34 | "ds = xr.tutorial.open_dataset('air_temperature')\n", 35 | "ds" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "ds.hvplot.contourf()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "There are lots of options exposed to control the style and contents of the `contourf` plot:" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "ds.mean(dim='time').hvplot.contourf(z='air', x='lon', y='lat', levels=20,\n", 61 | " clabel='T [K]', label='Mean Air temperature [K]',\n", 62 | " cmap='fire')" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "## Geographic Data" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "ds.hvplot.contourf(levels=20, geo=True, coastline=True, widget_location='left_top')" 79 | ] 80 | } 81 | ], 82 | "metadata": { 83 | "language_info": { 84 | "name": "python", 85 | "pygments_lexer": "ipython3" 86 | } 87 | }, 88 | "nbformat": 4, 89 | "nbformat_minor": 4 90 | } 91 | -------------------------------------------------------------------------------- /doc/reference/xarray/hist.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hist" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa\n", 17 | "import xarray as xr" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "`hist` is often a good way to start looking at data to get a sense of the distribution. Similar methods include [`kde`](kde.ipynb) (also available as `density`)." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "ds = xr.tutorial.open_dataset('air_temperature').load()\n", 34 | "air = ds.air\n", 35 | "air1d = air.sel(lon=285.,lat=40.)\n", 36 | "air1d" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "air1d.hvplot.hist()" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "Customize the plot by changing the title and bar color." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "air1d.hvplot.hist(title=\"Air Temperature over time at lat=40,lon285\", color='gray')" 62 | ] 63 | } 64 | ], 65 | "metadata": { 66 | "language_info": { 67 | "name": "python", 68 | "pygments_lexer": "ipython3" 69 | } 70 | }, 71 | "nbformat": 4, 72 | "nbformat_minor": 4 73 | } 74 | -------------------------------------------------------------------------------- /doc/reference/xarray/image.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Image" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "import xarray as xr\n", 26 | "\n", 27 | "ds = xr.tutorial.open_dataset('air_temperature')\n", 28 | "ds" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "When data values are available on an x, y grid, they can often be represented as an `image`." 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "ds.hvplot.image()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "This is equivalent to specifying:" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "ds.hvplot.image(x='lon', y='lat', z='air', groupby='time', cmap='kbc_r')" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "A simpler case would be to take the temperature at just one day. Here we'll show how to use `clabel` to control the colorbar and also demonstrate how when the data are symmetric around 0, the \"coolwarm\" colormap is used by default." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "time = '2014-01-01'\n", 77 | "data = ds.sel(time=time).mean('time') - 273 # convert to celsius\n", 78 | "\n", 79 | "data.hvplot.image(x='lon', y='lat', z='air', title=time, clabel='T [C]')" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "We can also override the colorbar ticks and labels with `cticks`, specified as an integer, list of ticks positions, or list of tuples of the tick positions and labels." 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "data.hvplot.image(x='lon', y='lat', z='air', title=time, clabel='T [C]', cticks=[(-40, \"Below Freezing\"), (0, \"Freezing\"), (40, \"Above Freezing\")])" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "## Geographic Data\n", 103 | "\n", 104 | "By setting `coastline=True`, we can add a coastline feature to the plot and coerce it to the proper aspect." 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "data.hvplot.image(coastline=True)" 114 | ] 115 | } 116 | ], 117 | "metadata": { 118 | "language_info": { 119 | "name": "python", 120 | "pygments_lexer": "ipython3" 121 | } 122 | }, 123 | "nbformat": 4, 124 | "nbformat_minor": 4 125 | } 126 | -------------------------------------------------------------------------------- /doc/reference/xarray/kde.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a8373dcf-f097-454d-b97a-2f4e7bf20e62", 6 | "metadata": {}, 7 | "source": [ 8 | "# Kde" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "2ccf9fd5-9d10-4522-961d-7e8d236213b2", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.xarray # noqa\n", 19 | "import xarray as xr" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "f7ed6c65-2280-4741-b89b-721110628547", 25 | "metadata": {}, 26 | "source": [ 27 | "Kernel density estimate (`kde`) provides a mechanism for showing the distribution and spread of the data. In `hvplot` the method is exposed both as `kde` and `density`." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "e8680d48-02b1-4480-96e3-d0fd7807a804", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "ds = xr.tutorial.open_dataset('air_temperature').load()\n", 38 | "air = ds.air\n", 39 | "air1d = air.sel(lat=[25, 50, 75])" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "id": "f33d3355-deaa-4bdf-befa-af20d2e46d7a", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "air1d.hvplot.kde('air', by='lat', alpha=0.5)" 50 | ] 51 | } 52 | ], 53 | "metadata": { 54 | "language_info": { 55 | "name": "python", 56 | "pygments_lexer": "ipython3" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 5 61 | } 62 | -------------------------------------------------------------------------------- /doc/reference/xarray/line.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Line" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa\n", 17 | "import xarray as xr" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "`line` is useful when data is continuous and has a continuous axis." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "ds = xr.tutorial.open_dataset('air_temperature').load()\n", 34 | "air = ds.air\n", 35 | "air1d = air.sel(lon=285.,lat=40.)\n", 36 | "air1d" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "air1d.hvplot.line()" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "Customize the plot by changing the title and line color." 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "air1d.hvplot.line(title=\"Air Temperature over time at lat=40,lon285\",line_color='gray')" 62 | ] 63 | } 64 | ], 65 | "metadata": { 66 | "language_info": { 67 | "name": "python", 68 | "pygments_lexer": "ipython3" 69 | } 70 | }, 71 | "nbformat": 4, 72 | "nbformat_minor": 4 73 | } 74 | -------------------------------------------------------------------------------- /doc/reference/xarray/quadmesh.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Quadmesh" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "import xarray as xr\n", 26 | "\n", 27 | "ds = xr.tutorial.open_dataset('rasm')\n", 28 | "ds" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "`quadmesh` can be slower that `image`, but it allows you to plot values on an irregular grid by representing each value as a polygon." 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "ds.Tair.hvplot.quadmesh(x='xc', y='yc', geo=True, widget_location='bottom')" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "To reduce the render time or the size of the saved plot, use `rasterize` to aggregate the values to the pixel. It is recommended that when rasterizing geo plots, you project **before** rasterizing, by setting `project=True`." 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "ds.Tair.hvplot.quadmesh(x='xc', y='yc', geo=True, widget_location='bottom', rasterize=True, project=True)" 61 | ] 62 | } 63 | ], 64 | "metadata": { 65 | "language_info": { 66 | "name": "python", 67 | "pygments_lexer": "ipython3" 68 | } 69 | }, 70 | "nbformat": 4, 71 | "nbformat_minor": 4 72 | } 73 | -------------------------------------------------------------------------------- /doc/reference/xarray/rgb.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Rgb" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import hvplot.xarray # noqa" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "`rgb` can be used to display images that are distributed as three separate \"channels\" or \"bands\"." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from hvplot.sample_data import landuse\n", 33 | "\n", 34 | "da = landuse(landuse='airplane', id=90).read()\n", 35 | "da" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "Since rgb images are stored starting at the top left pixel, we should start there when plotting to make sure that we get the picture in the correct orientation. To accomplish this, we use `flip_yaxis`." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "da.hvplot.rgb(x='x', y='y', bands='channel', data_aspect=1, flip_yaxis=True, xaxis=False, yaxis=None)" 52 | ] 53 | } 54 | ], 55 | "metadata": { 56 | "language_info": { 57 | "name": "python", 58 | "pygments_lexer": "ipython3" 59 | } 60 | }, 61 | "nbformat": 4, 62 | "nbformat_minor": 4 63 | } 64 | -------------------------------------------------------------------------------- /doc/reference/xarray/violin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "cc4ff857-13b2-4f43-97dd-502a0703d276", 6 | "metadata": {}, 7 | "source": [ 8 | "# Violin" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "id": "2ccf9fd5-9d10-4522-961d-7e8d236213b2", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import hvplot.xarray # noqa\n", 19 | "import xarray as xr" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "f7ed6c65-2280-4741-b89b-721110628547", 25 | "metadata": {}, 26 | "source": [ 27 | "`violin` plots are similar to box plots, but provide a better sense of the distribution of data. Note that `violin` plots depend on the `scipy` library." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "e0f6ecc7-0f6a-4590-9c98-da10a674b9b0", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "ds = xr.tutorial.open_dataset('air_temperature').load()\n", 38 | "air = ds.air\n", 39 | "air" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "id": "2a137994-0a9d-4a75-8192-1e4bb4ead6c5", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "air.hvplot.violin(y='air', by='lat', color='lat', cmap='Category20', title=\"Air Temperature vs. latitude\")" 50 | ] 51 | } 52 | ], 53 | "metadata": { 54 | "language_info": { 55 | "name": "python", 56 | "pygments_lexer": "ipython3" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 5 61 | } 62 | -------------------------------------------------------------------------------- /doc/topics.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 12 |

You should have been redirected.

13 | If not, click here to continue. 14 | 15 | 16 | -------------------------------------------------------------------------------- /doc/tutorials/index.md: -------------------------------------------------------------------------------- 1 | # Tutorials 2 | 3 | Welcome to the Tutorials section. Here, you will find clear, step-by-step guides to help you master hvPlot and explore the full [HoloViz](https://holoviz.org/) 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. 4 | 5 | ## Internal tutorials 6 | 7 | ::::{grid} 1 2 2 3 8 | :gutter: 1 1 1 2 9 | 10 | :::{grid-item-card} {octicon}`book;2.5em;sd-mr-1 sd-animate-grow50` Getting Started 11 | :link: getting_started 12 | :link-type: doc 13 | 14 | Get started with hvPlot using this quick tutorial. 15 | ::: 16 | 17 | :::{grid-item-card} {octicon}`repo-template;2.5em;sd-mr-1 sd-animate-grow50` Coming From Pandas? 18 | :link: getting_started_pandas 19 | :link-type: doc 20 | 21 | Get started with hvPlot as a Pandas user. 22 | ::: 23 | 24 | :::: 25 | 26 | ## External tutorials 27 | 28 | ::::{grid} 1 2 2 3 29 | :gutter: 1 1 1 2 30 | 31 | :::{grid-item-card} {octicon}`link;2.5em;sd-mr-1 sd-animate-grow50` Holoviz Tutorial 32 | :link: https://holoviz.org/tutorial/index.html 33 | 34 | Explore all the HoloViz tools in this comprehensive tutorial. 35 | ::: 36 | 37 | :::: 38 | 39 | ```{toctree} 40 | :titlesonly: 41 | :hidden: 42 | :maxdepth: 2 43 | 44 | Getting Started 45 | Using hvPlot as a Pandas user 46 | HoloViz Tutorial 47 | ``` 48 | -------------------------------------------------------------------------------- /doc/user_guide/index.md: -------------------------------------------------------------------------------- 1 | # User Guide 2 | 3 | The user guide provides a detailed introduction to the API and 4 | features of hvPlot. In the [Introduction](Introduction.ipynb) you 5 | will learn how to activate the plotting API and start using it. Next 6 | you will learn to use the API for tabular data and get an overview of 7 | the [types of plots](Plotting.ipynb) you can generate; including how to customize 8 | interactivity using [widgets](Widgets.ipynb). Next is an overview on how to 9 | [display and save plots](Viewing.ipynb) in the notebook, on the 10 | commandline, and from a script. Another section will introduce you to 11 | generating [subplots](Subplots.ipynb) from your data. 12 | 13 | Once the basics are covered you can learn how to use the plotting API 14 | for specific types of data including [streaming data](Streaming.ipynb), [gridded data](Gridded_Data.ipynb) 15 | [network graphs](NetworkX.ipynb), [geographic data](Geographic_Data.ipynb), 16 | and [timeseries data](Timeseries_Data.ipynb). These sections are not meant 17 | to be read in a particular order; you should take a look at any that seem 18 | relevant to your data. 19 | 20 | The [interactive](Interactive.ipynb) user guide introduces you to the 21 | ability to use the APIs of your favorite data analysis libraries 22 | interactively by allowing you to pass in widgets in place of constant 23 | arguments. This will provide you with an invaluable tool to perform 24 | exploratory analyses quickly but also build powerful and complex data 25 | analysis pipelines using APIs you are already familiar with. 26 | 27 | Lastly the [statistical plots](Statistical_Plots.ipynb) section will 28 | take you through a number of specialized plot types modelled on the 29 | pandas.plotting module. 30 | 31 | **Overview**: 32 | 33 | - [Introduction](Introduction) 34 | Introduction to hvPlot and how to start using it. 35 | - [Plotting with Bokeh](Plotting) 36 | Overview of plotting your data with hvPlot and Bokeh. 37 | - [Plotting with Matplotlib](Plotting_with_Matplotlib) 38 | Overview of plotting your data with hvPlot and Matplotib. 39 | - [Plotting with Plotly](Plotting_with_Plotly) 40 | Overview of plotting your data with hvPlot and Plotly. 41 | - [Interactive](Interactive) 42 | Interactive APIs for data exploration. 43 | - [Widgets](Widgets) 44 | Adding and customizing interactivity using Panel widgets. 45 | - [Plotting Extensions](Plotting_Extensions) 46 | Changing the plotting extension. 47 | - [Exploring data](Explorer) 48 | Exploring data with user interface. 49 | - [Viewing](Viewing) 50 | Displaying and saving plots in the notebook, at the command prompt, or in scripts. 51 | - [Subplots](Subplots) 52 | How to generate subplots and grids. 53 | - [Streaming](Streaming) 54 | How to use hvPlot for streaming plots with the streamz library. 55 | - [Gridded Data](Gridded_Data) 56 | How to use hvPlot for plotting XArray-based gridded data. 57 | - [Network Graphs](NetworkX) 58 | How to use hvPlot for plotting NetworkX graphs. 59 | - [Geographic Data](Geographic_Data) 60 | Using GeoViews, Cartopy, GeoPandas and spatialpandas to plot data in geographic coordinate systems. 61 | - [Timeseries Data](Timeseries_Data) 62 | Using hvPlot when working with timeseries data. 63 | - [Large Timeseries Data](Large_Timeseries) 64 | Using hvPlot when working with large timeseries data. 65 | - [Statistical Plots](Statistical_Plots) 66 | A number of statistical plot types modeled on the pandas.plotting module. 67 | 68 | ```{toctree} 69 | :hidden: true 70 | :maxdepth: 2 71 | :titlesonly: true 72 | 73 | Introduction 74 | Plotting with Bokeh 75 | Plotting with Matplotlib 76 | Plotting with Plotly 77 | Interactive 78 | Widgets 79 | Plotting Extensions 80 | Exploring data 81 | Viewing 82 | Subplots 83 | Streaming 84 | Gridded Data 85 | Network Graphs 86 | Geographic Data 87 | Timeseries Data 88 | Large Timeseries 89 | Statistical Plots 90 | ``` 91 | -------------------------------------------------------------------------------- /hvplot/cudf.py: -------------------------------------------------------------------------------- 1 | from .interactive import Interactive 2 | 3 | 4 | def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False): 5 | from . import hvPlotTabular, post_patch, _module_extensions 6 | 7 | try: 8 | import cudf 9 | except ImportError: 10 | raise ImportError('Could not patch plotting API onto cuDF. cuDF could not be imported.') 11 | 12 | if 'hvplot.cudf' not in _module_extensions: 13 | _patch_plot = lambda self: hvPlotTabular(self) # noqa: E731 14 | _patch_plot.__doc__ = hvPlotTabular.__call__.__doc__ 15 | plot_prop = property(_patch_plot) 16 | setattr(cudf.DataFrame, name, plot_prop) 17 | setattr(cudf.Series, name, plot_prop) 18 | 19 | _patch_interactive = lambda self: Interactive(self) # noqa: E731 20 | _patch_interactive.__doc__ = Interactive.__call__.__doc__ 21 | interactive_prop = property(_patch_interactive) 22 | setattr(cudf.DataFrame, interactive, interactive_prop) 23 | setattr(cudf.Series, interactive, interactive_prop) 24 | 25 | _module_extensions.add('hvplot.cudf') 26 | 27 | post_patch(extension, logo) 28 | 29 | 30 | patch() 31 | -------------------------------------------------------------------------------- /hvplot/dask.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from .interactive import Interactive 4 | 5 | 6 | class DaskInteractive(Interactive): 7 | @classmethod 8 | def applies(cls, obj): 9 | if 'dask.dataframe' in sys.modules: 10 | import dask.dataframe as dd 11 | 12 | return isinstance(obj, (dd.Series, dd.DataFrame)) 13 | return False 14 | 15 | def compute(self): 16 | self._method = 'compute' 17 | return self.__call__() 18 | 19 | 20 | def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False): 21 | from . import hvPlotTabular, post_patch, _module_extensions 22 | 23 | try: 24 | import dask.dataframe as dd 25 | except ImportError: 26 | raise ImportError('Could not patch plotting API onto dask. Dask could not be imported.') 27 | 28 | if 'hvplot.dask' not in _module_extensions: 29 | _patch_plot = lambda self: hvPlotTabular(self) # noqa: E731 30 | _patch_plot.__doc__ = hvPlotTabular.__call__.__doc__ 31 | plot_prop = property(_patch_plot) 32 | setattr(dd.DataFrame, name, plot_prop) 33 | setattr(dd.Series, name, plot_prop) 34 | 35 | _patch_interactive = lambda self: DaskInteractive(self) # noqa: E731 36 | _patch_interactive.__doc__ = DaskInteractive.__call__.__doc__ 37 | interactive_prop = property(_patch_interactive) 38 | setattr(dd.DataFrame, interactive, interactive_prop) 39 | setattr(dd.Series, interactive, interactive_prop) 40 | 41 | _module_extensions.add('hvplot.dask') 42 | 43 | post_patch(extension, logo) 44 | 45 | 46 | patch() 47 | -------------------------------------------------------------------------------- /hvplot/datasets.yaml: -------------------------------------------------------------------------------- 1 | sources: 2 | airline_flights: 3 | description: Airline Flight data 4 | driver: parquet 5 | cache: 6 | - argkey: urlpath 7 | regex: 'assets.holoviews.org/data/' 8 | type: file 9 | args: 10 | urlpath: 's3://assets.holoviews.org/data/airline_flights.parq' 11 | storage_options: 12 | anon: true 13 | client_kwargs: {'region_name': "eu-west-1"} 14 | 15 | us_crime: 16 | description: US Crime data 17 | driver: csv 18 | args: 19 | urlpath: '{{ CATALOG_DIR }}/data/crime.csv' 20 | metadata: 21 | url: https://web.archive.org/web/20201031163816/https://www.ucrdatatool.gov/Search/Crime/State/StatebyState.cfm 22 | plots: 23 | example: 24 | kind: line 25 | y: ['Robbery', 'Burglary'] 26 | x: 'Year' 27 | 28 | landuse: 29 | description: Image matching given landuse and id from UCMerced_LandUse/Image. 30 | origin: http://weegee.vision.ucmerced.edu/datasets/landuse.html 31 | driver: xarray_image 32 | cache: 33 | - argkey: urlpath 34 | regex: 'earth-data/UCMerced_LandUse' 35 | type: file 36 | parameters: 37 | landuse: 38 | description: which landuse to collect 39 | type: str 40 | default: airplane 41 | id: 42 | description: which id to collect 43 | type: int 44 | default: 0 45 | args: 46 | urlpath: "s3://earth-data/UCMerced_LandUse/Images/{{ landuse }}/{{ landuse }}{{ '%02d' % id }}.tif" 47 | storage_options: 48 | anon: true 49 | -------------------------------------------------------------------------------- /hvplot/duckdb.py: -------------------------------------------------------------------------------- 1 | """Adds the `.hvplot` method to duckdb.DuckDBPyRelation and duckdb.DuckDBPyConnection""" 2 | 3 | 4 | def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False): 5 | from hvplot.plotting.core import hvPlotTabularDuckDB 6 | from . import post_patch, _module_extensions 7 | 8 | if 'hvplot.duckdb' not in _module_extensions: 9 | try: 10 | import duckdb 11 | except ImportError: 12 | raise ImportError( 13 | 'Could not patch plotting API onto DuckDB. DuckDB could not be imported.' 14 | ) 15 | 16 | # Patching for DuckDBPyRelation and DuckDBPyConnection 17 | _patch_duckdb_plot = lambda self: hvPlotTabularDuckDB(self) # noqa: E731 18 | _patch_duckdb_plot.__doc__ = hvPlotTabularDuckDB.__call__.__doc__ 19 | plot_prop_duckdb = property(_patch_duckdb_plot) 20 | setattr(duckdb.DuckDBPyRelation, name, plot_prop_duckdb) 21 | setattr(duckdb.DuckDBPyConnection, name, plot_prop_duckdb) 22 | _module_extensions.add('hvplot.duckdb') 23 | 24 | post_patch(extension, logo) 25 | 26 | 27 | patch() 28 | -------------------------------------------------------------------------------- /hvplot/fugue.py: -------------------------------------------------------------------------------- 1 | """ 2 | Experimental support for fugue. 3 | """ 4 | 5 | from typing import Any 6 | 7 | import panel as _pn 8 | 9 | from . import hvPlotTabular, post_patch, _module_extensions 10 | from .util import _fugue_ipython 11 | 12 | 13 | def patch(name='hvplot', extension='bokeh', logo=False): 14 | try: 15 | from fugue import DataFrames, Outputter 16 | from fugue.extensions import namespace_candidate, parse_outputter 17 | except ImportError: 18 | raise ImportError( 19 | 'Could not add fugue support as it could not be imported. ' 20 | 'Please make sure you have installed fugue in your environment.' 21 | ) 22 | 23 | import hvplot.pandas # noqa: F401 24 | 25 | class _Visualize(Outputter): 26 | def __init__(self, func: str) -> None: 27 | super().__init__() 28 | self._func = func 29 | getattr(hvPlotTabular, func) # ensure the func exists 30 | 31 | def process(self, dfs: DataFrames) -> None: 32 | """ 33 | Process the dataframes and output the result as 34 | a pn.Column. 35 | 36 | Parameters: 37 | ----------- 38 | dfs: fugue.DataFrames 39 | """ 40 | charts = [] 41 | for df in dfs.values(): 42 | params = dict(self.params) 43 | opts: dict[str, Any] = params.pop('opts', {}) 44 | chart = getattr(df.as_pandas().hvplot, self._func)(**params).opts(**opts) 45 | charts.append(chart) 46 | col = _pn.Column(*charts) 47 | try: 48 | if not _fugue_ipython: 49 | get_ipython() 50 | except NameError: 51 | col.show() # in script 52 | else: 53 | from IPython.display import display 54 | 55 | display(col) # in notebook 56 | 57 | if 'hvplot.fugue' not in _module_extensions: 58 | 59 | @parse_outputter.candidate(namespace_candidate(name, lambda x: isinstance(x, str))) 60 | def _parse_hvplot(obj: tuple[str, str]) -> Outputter: 61 | return _Visualize(obj[1]) 62 | 63 | _module_extensions.add('hvplot.fugue') 64 | 65 | post_patch(extension, logo) 66 | 67 | 68 | patch() 69 | -------------------------------------------------------------------------------- /hvplot/ibis.py: -------------------------------------------------------------------------------- 1 | """ 2 | Experimental support for ibis. 3 | """ 4 | 5 | 6 | def patch(name='hvplot', extension='bokeh', logo=False): 7 | from . import hvPlotTabular, post_patch, _module_extensions 8 | 9 | try: 10 | import ibis 11 | except ImportError: 12 | raise ImportError('Could not patch plotting API onto ibis. Ibis could not be imported.') 13 | 14 | if 'hvplot.ibis' not in _module_extensions: 15 | _patch_plot = lambda self: hvPlotTabular(self) # noqa: E731 16 | _patch_plot.__doc__ = hvPlotTabular.__call__.__doc__ 17 | patch_property = property(_patch_plot) 18 | setattr(ibis.Expr, name, patch_property) 19 | 20 | _module_extensions.add('hvplot.ibis') 21 | 22 | post_patch(extension, logo) 23 | 24 | 25 | patch() 26 | -------------------------------------------------------------------------------- /hvplot/intake.py: -------------------------------------------------------------------------------- 1 | from packaging.version import Version 2 | 3 | from . import hvPlot, post_patch, _module_extensions 4 | 5 | 6 | def patch(name='hvplot', extension='bokeh', logo=False): 7 | try: 8 | import intake 9 | except ImportError: 10 | raise ImportError( 11 | 'Could not patch plotting API onto intake. intake could not be imported.' 12 | ) 13 | 14 | if 'hvplot.intake' not in _module_extensions: 15 | _patch_plot = lambda self: hvPlot(self) # noqa: E731 16 | _patch_plot.__doc__ = hvPlot.__call__.__doc__ 17 | patch_property = property(_patch_plot) 18 | setattr(intake.source.base.DataSource, name, patch_property) 19 | 20 | _module_extensions.add('hvplot.intake') 21 | 22 | post_patch(extension, logo) 23 | 24 | 25 | try: 26 | import intake.plotting # noqa 27 | 28 | patch() 29 | except Exception: 30 | import intake 31 | 32 | if Version(intake.__version__) <= Version('0.1.5'): 33 | patch() 34 | patch(name='plot') 35 | else: 36 | post_patch(extension='bokeh', logo=False) 37 | -------------------------------------------------------------------------------- /hvplot/pandas.py: -------------------------------------------------------------------------------- 1 | """Adds the `.hvplot` method to pd.DataFrame and pd.Series""" 2 | 3 | from .interactive import Interactive 4 | 5 | 6 | def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False): 7 | from . import hvPlotTabular, post_patch, _module_extensions 8 | 9 | try: 10 | import pandas as pd 11 | except ImportError: 12 | raise ImportError( 13 | 'Could not patch plotting API onto pandas. Pandas could not be imported.' 14 | ) 15 | 16 | if 'hvplot.pandas' not in _module_extensions: 17 | _patch_plot = lambda self: hvPlotTabular(self) # noqa: E731 18 | _patch_plot.__doc__ = hvPlotTabular.__call__.__doc__ 19 | plot_prop = property(_patch_plot) 20 | setattr(pd.DataFrame, name, plot_prop) 21 | setattr(pd.Series, name, plot_prop) 22 | 23 | _patch_interactive = lambda self: Interactive(self) # noqa: E731 24 | _patch_interactive.__doc__ = Interactive.__call__.__doc__ 25 | interactive_prop = property(_patch_interactive) 26 | setattr(pd.DataFrame, interactive, interactive_prop) 27 | setattr(pd.Series, interactive, interactive_prop) 28 | _module_extensions.add('hvplot.pandas') 29 | 30 | post_patch(extension, logo) 31 | 32 | 33 | patch() 34 | -------------------------------------------------------------------------------- /hvplot/plotting/__init__.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | import holoviews as hv 4 | from ..util import with_hv_extension, is_duckdb, is_polars, _find_stack_level 5 | 6 | from .core import hvPlot, hvPlotTabular # noqa 7 | 8 | from .andrews_curves import andrews_curves # noqa 9 | from .parallel_coordinates import parallel_coordinates # noqa 10 | from .lag_plot import lag_plot # noqa 11 | from .scatter_matrix import scatter_matrix # noqa 12 | 13 | 14 | @with_hv_extension 15 | def plot(data, kind, **kwargs): 16 | # drop reuse_plot 17 | kwargs.pop('reuse_plot', None) 18 | 19 | # replace with shared_axes 20 | sharex = kwargs.pop('sharex', None) 21 | sharey = kwargs.pop('sharey', None) 22 | if sharex is not None and sharey is not None: 23 | kwargs['shared_axes'] = sharex or sharey 24 | elif sharex is not None: 25 | kwargs['shared_axes'] = sharex 26 | elif sharey is not None: 27 | kwargs['shared_axes'] = sharey 28 | 29 | # drop all kwargs that are set to None 30 | no_none_kwargs = {} 31 | for k, v in kwargs.items(): 32 | if v is not None: 33 | no_none_kwargs[k] = v 34 | 35 | if is_polars(data): 36 | from .core import hvPlotTabularPolars 37 | 38 | return hvPlotTabularPolars(data)(kind=kind, **no_none_kwargs) 39 | 40 | elif is_duckdb(data): 41 | warnings.warn( 42 | 'Allowing to pass DuckDB data objects to the plot function is ' 43 | 'deprecated and will be removed in a future version. ' 44 | 'Use `import hvplot.duckdb` instead.', 45 | FutureWarning, 46 | stacklevel=_find_stack_level(), 47 | ) 48 | from .core import hvPlotTabularDuckDB 49 | 50 | return hvPlotTabularDuckDB(data)(kind=kind, **no_none_kwargs) 51 | return hvPlotTabular(data)(kind=kind, **no_none_kwargs) 52 | 53 | 54 | def boxplot_series(*args, **kwargs): 55 | return plot(*args, kind='box', **kwargs) 56 | 57 | 58 | def boxplot_frame(*args, **kwargs): 59 | return plot(*args, kind='box', **kwargs) 60 | 61 | 62 | def boxplot_frame_groupby(grouped, **kwargs): 63 | width = kwargs.pop('width', 300) 64 | subplots = kwargs.pop('subplots', True) 65 | layout = hv.Layout if subplots else hv.Overlay 66 | plots = [ 67 | plot(data=data, kind='box', title=name, width=width, **kwargs) for name, data in grouped 68 | ] 69 | return layout(plots) 70 | 71 | 72 | def hist_series(*args, **kwargs): 73 | return plot(*args, kind='hist', **kwargs) 74 | 75 | 76 | def hist_frame(*args, **kwargs): 77 | return plot(*args, kind='hist', **kwargs) 78 | -------------------------------------------------------------------------------- /hvplot/plotting/andrews_curves.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | import holoviews as hv 5 | import colorcet as cc 6 | 7 | from ..backend_transforms import _transfer_opts_cur_backend 8 | from ..util import with_hv_extension 9 | 10 | 11 | @with_hv_extension 12 | def andrews_curves( 13 | data, 14 | class_column, 15 | samples=200, 16 | alpha=0.5, 17 | width=600, 18 | height=300, 19 | cmap=None, 20 | colormap=None, 21 | **kwds, 22 | ): 23 | """ 24 | Generate a plot of Andrews curves, for visualising clusters of 25 | multivariate data. 26 | 27 | Andrews curves have the functional form: 28 | 29 | .. math:: 30 | f(t) = \\frac{x_1}{\\sqrt{2}} + x_2 \\sin(t) + x_3 \\cos(t) + 31 | x_4 \\sin(2t) + x_5 \\cos(2t) + \\cdots 32 | 33 | Where :math:`x` coefficients correspond to the values of each dimension 34 | and :math:`t` is linearly spaced between :math:`-\\pi` and :math:`+\\pi`. 35 | Each row of frame then corresponds to a single curve. 36 | 37 | Parameters 38 | ---------- 39 | frame : DataFrame 40 | Data to be plotted, preferably normalized to (0.0, 1.0) 41 | class_column : str 42 | Column name containing class names 43 | samples : int, optional 44 | Number of samples to draw 45 | alpha : float, optional 46 | The transparency of the lines 47 | cmap/colormap : str or colormap object 48 | Colormap to use for groups 49 | 50 | Returns 51 | ------- 52 | obj : HoloViews object 53 | The HoloViews representation of the plot. 54 | 55 | See Also 56 | -------- 57 | pandas.plotting.parallel_coordinates : matplotlib version of this routine 58 | """ 59 | t = np.linspace(-np.pi, np.pi, samples) 60 | vals = data.drop(class_column, axis=1).values.T 61 | 62 | curves = np.outer(vals[0] / np.sqrt(2), np.ones_like(t)) 63 | for i in range(1, len(vals)): 64 | ft = ((i + 1) // 2) * t 65 | if i % 2 == 1: 66 | curves += np.outer(vals[i], np.sin(ft)) 67 | else: 68 | curves += np.outer(vals[i], np.cos(ft)) 69 | 70 | df = pd.DataFrame( 71 | { 72 | 't': np.tile(t, curves.shape[0]), 73 | 'sample': np.repeat(np.arange(curves.shape[0]), curves.shape[1]), 74 | 'value': curves.ravel(), 75 | class_column: np.repeat(data[class_column], samples), 76 | } 77 | ) 78 | 79 | labelled = ['x'] 80 | options = { 81 | 'Overlay': dict(legend_limit=5000), 82 | 'Curve': dict(kwds, labelled=labelled, alpha=alpha, width=width, height=height, **kwds), 83 | } 84 | dataset = hv.Dataset(df) 85 | groups = dataset.to(hv.Curve, 't', 'value').overlay('sample').items() 86 | 87 | if cmap and colormap: 88 | raise TypeError('Only specify one of `cmap` and `colormap`.') 89 | cmap = cmap or colormap or cc.palette['glasbey_category10'] 90 | colors = hv.plotting.util.process_cmap(cmap, categorical=True, ncolors=len(groups)) 91 | 92 | el = hv.Overlay( 93 | [ 94 | curve.relabel(k).options('Curve', color=c, backend='bokeh') 95 | for c, (k, v) in zip(colors, groups) 96 | for curve in v 97 | ] 98 | ).options(options, backend='bokeh') 99 | el = _transfer_opts_cur_backend(el) 100 | return el 101 | -------------------------------------------------------------------------------- /hvplot/plotting/lag_plot.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | from ..util import with_hv_extension 5 | from .core import hvPlotTabular 6 | 7 | 8 | @with_hv_extension 9 | def lag_plot(data, lag=1, **kwds): 10 | """Lag plot for time series. 11 | 12 | A lag plot is a scatter plot of a time series against a lag of itself. It helps 13 | in visualizing the temporal dependence between observations by plotting the values 14 | at time `t` on the x-axis and the values at time `t + lag` on the y-axis. 15 | 16 | Parameters 17 | ---------- 18 | data : Series 19 | The time series to visualize. 20 | lag : int, default 1 21 | Lag length of the scatter plot. 22 | **kwds : optional 23 | hvplot.scatter options 24 | 25 | Returns 26 | ------- 27 | obj : HoloViews object 28 | The HoloViews representation of the plot. 29 | """ 30 | if lag != int(lag) or int(lag) <= 0: 31 | raise ValueError('lag must be a positive integer') 32 | lag = int(lag) 33 | 34 | values = data.values 35 | y1 = 'y(t)' 36 | y2 = f'y(t + {lag})' 37 | lags = pd.DataFrame({y1: values[:-lag].T.ravel(), y2: values[lag:].T.ravel()}) 38 | if isinstance(data, pd.DataFrame): 39 | lags['variable'] = np.repeat(data.columns, lags.shape[0] / data.shape[1]) 40 | kwds['c'] = 'variable' 41 | return hvPlotTabular(lags)(y1, y2, kind='scatter', **kwds) 42 | -------------------------------------------------------------------------------- /hvplot/plotting/parallel_coordinates.py: -------------------------------------------------------------------------------- 1 | import holoviews as hv 2 | import colorcet as cc 3 | 4 | from ..backend_transforms import _transfer_opts_cur_backend 5 | from ..util import with_hv_extension 6 | 7 | 8 | @with_hv_extension 9 | def parallel_coordinates( 10 | data, 11 | class_column, 12 | cols=None, 13 | alpha=0.5, 14 | width=600, 15 | height=300, 16 | var_name='variable', 17 | value_name='value', 18 | cmap=None, 19 | colormap=None, 20 | **kwds, 21 | ): 22 | """ 23 | Parallel coordinates plotting. 24 | 25 | To show a set of points in an n-dimensional space, a backdrop is drawn 26 | consisting of n parallel lines. A point in n-dimensional space is 27 | represented as a polyline with vertices on the parallel axes; the 28 | position of the vertex on the i-th axis corresponds to the i-th coordinate 29 | of the point. 30 | 31 | Parameters 32 | ---------- 33 | frame : DataFrame 34 | The DataFrame to be plotted. 35 | class_column : str 36 | Column name containing class names 37 | cols : list, optional 38 | A list of column names to use 39 | alpha : float, optional 40 | The transparency of the lines 41 | cmap/colormap : str or colormap object 42 | Colormap to use for groups 43 | 44 | Returns 45 | ------- 46 | obj : HoloViews object 47 | The HoloViews representation of the plot. 48 | 49 | See Also 50 | -------- 51 | pandas.plotting.parallel_coordinates : matplotlib version of this routine 52 | """ 53 | # Transform the dataframe to be used in Vega-Lite 54 | if cols is not None: 55 | data = data[list(cols) + [class_column]] 56 | cols = data.columns 57 | df = data.reset_index() 58 | index = (set(df.columns) - set(cols)).pop() 59 | assert index in df.columns 60 | df = df.melt([index, class_column], var_name=var_name, value_name=value_name) 61 | 62 | labelled = [] if var_name == 'variable' else ['x'] 63 | if value_name != 'value': 64 | labelled.append('y') 65 | options = { 66 | 'Curve': dict(kwds, labelled=labelled, alpha=alpha, width=width, height=height), 67 | 'Overlay': dict(legend_limit=5000), 68 | } 69 | 70 | dataset = hv.Dataset(df) 71 | groups = dataset.to(hv.Curve, var_name, value_name).overlay(index).items() 72 | 73 | if cmap and colormap: 74 | raise TypeError('Only specify one of `cmap` and `colormap`.') 75 | cmap = cmap or colormap or cc.palette['glasbey_category10'] 76 | colors = hv.plotting.util.process_cmap(cmap, categorical=True, ncolors=len(groups)) 77 | 78 | el = hv.Overlay( 79 | [ 80 | curve.relabel(k).options('Curve', color=c, backend='bokeh') 81 | for c, (k, v) in zip(colors, groups) 82 | for curve in v 83 | ] 84 | ).options(options, backend='bokeh') 85 | el = _transfer_opts_cur_backend(el) 86 | return el 87 | -------------------------------------------------------------------------------- /hvplot/polars.py: -------------------------------------------------------------------------------- 1 | """Adds the `.hvplot` method to pl.DataFrame, pl.LazyFrame and pl.Series""" 2 | 3 | from hvplot import post_patch, _module_extensions 4 | from hvplot.plotting.core import hvPlotTabularPolars 5 | 6 | 7 | def patch(name='hvplot', extension='bokeh', logo=False): 8 | try: 9 | import polars as pl 10 | except ImportError: 11 | raise ImportError( 12 | 'Could not patch plotting API onto Polars. Polars could not be imported.' 13 | ) 14 | if 'hvplot.polars' not in _module_extensions: 15 | pl.api.register_dataframe_namespace(name)(hvPlotTabularPolars) 16 | pl.api.register_series_namespace(name)(hvPlotTabularPolars) 17 | pl.api.register_lazyframe_namespace(name)(hvPlotTabularPolars) 18 | _module_extensions.add('hvplot.polars') 19 | 20 | post_patch(extension, logo) 21 | 22 | 23 | patch() 24 | -------------------------------------------------------------------------------- /hvplot/sample_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | Loads hvPlot sample data using intake catalogue. 3 | """ 4 | 5 | import os 6 | 7 | try: 8 | from intake import open_catalog 9 | import intake_parquet # noqa 10 | import intake_xarray # noqa 11 | import s3fs # noqa 12 | except ImportError: 13 | raise ImportError( 14 | """Loading hvPlot sample data requires: 15 | * intake 16 | * intake-parquet 17 | * intake-xarray 18 | * s3fs 19 | Install these using conda or pip before loading data.""" 20 | ) 21 | 22 | _file_path = os.path.dirname(__file__) 23 | _cat_path = os.path.join(_file_path, 'datasets.yaml') 24 | 25 | # Load catalogue 26 | catalogue = open_catalog(_cat_path) 27 | 28 | # Add catalogue entries to namespace 29 | for _c in catalogue: 30 | globals()[_c] = catalogue[_c] 31 | -------------------------------------------------------------------------------- /hvplot/streamz.py: -------------------------------------------------------------------------------- 1 | def patch(name='hvplot', extension='bokeh', logo=False): 2 | from . import hvPlotTabular, post_patch, _module_extensions 3 | 4 | try: 5 | import streamz.dataframe as sdf 6 | except ImportError: 7 | raise ImportError( 8 | 'Could not patch plotting API onto streamz. Streamz could not be imported.' 9 | ) 10 | if 'hvplot.streamz' not in _module_extensions: 11 | _patch_plot = lambda self: hvPlotTabular(self) # noqa: E731 12 | _patch_plot.__doc__ = hvPlotTabular.__call__.__doc__ 13 | patch_property = property(_patch_plot) 14 | setattr(sdf.DataFrame, name, patch_property) 15 | setattr(sdf.DataFrames, name, patch_property) 16 | setattr(sdf.Series, name, patch_property) 17 | setattr(sdf.Seriess, name, patch_property) 18 | 19 | _module_extensions.add('hvplot.streamz') 20 | 21 | post_patch(extension, logo) 22 | 23 | 24 | patch() 25 | -------------------------------------------------------------------------------- /hvplot/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/hvplot/tests/__init__.py -------------------------------------------------------------------------------- /hvplot/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import dask 2 | import param 3 | import pytest 4 | 5 | from packaging.version import Version 6 | 7 | param.parameterized.warnings_as_exceptions = True 8 | 9 | optional_markers = { 10 | 'geo': { 11 | 'help': 'Run the tests that require GeoViews', 12 | 'marker-descr': 'Geo test marker', 13 | 'skip-reason': 'Test only runs with the --geo option.', 14 | }, 15 | } 16 | 17 | 18 | def pytest_addoption(parser): 19 | for marker, info in optional_markers.items(): 20 | parser.addoption(f'--{marker}', action='store_true', default=False, help=info['help']) 21 | 22 | 23 | def pytest_configure(config): 24 | for marker, info in optional_markers.items(): 25 | config.addinivalue_line('markers', '{}: {}'.format(marker, info['marker-descr'])) 26 | 27 | 28 | def pytest_collection_modifyitems(config, items): 29 | skipped, selected = [], [] 30 | markers = [m for m in optional_markers if config.getoption(f'--{m}')] 31 | empty = not markers 32 | for item in items: 33 | if empty and any(m in item.keywords for m in optional_markers): 34 | skipped.append(item) 35 | elif empty: 36 | selected.append(item) 37 | elif not empty and any(m in item.keywords for m in markers): 38 | selected.append(item) 39 | else: 40 | skipped.append(item) 41 | 42 | config.hook.pytest_deselected(items=skipped) 43 | items[:] = selected 44 | 45 | 46 | if Version(dask.__version__).release < (2025, 1, 0): 47 | # From Dask 2024.3.0 they now use `dask_expr` by default 48 | # https://github.com/dask/dask/issues/10995 49 | dask.config.set({'dataframe.query-planning': False}) 50 | 51 | 52 | @pytest.fixture 53 | def disable_param_warnings_as_exceptions(): 54 | original = param.parameterized.warnings_as_exceptions 55 | param.parameterized.warnings_as_exceptions = False 56 | try: 57 | yield 58 | finally: 59 | param.parameterized.warnings_as_exceptions = original 60 | -------------------------------------------------------------------------------- /hvplot/tests/data/README.md: -------------------------------------------------------------------------------- 1 | # Test data 2 | 3 | Test files required by the test suite: 4 | 5 | * The RGB-red.byte.tif file was obtained from [rasterio](https://github.com/rasterio/rasterio) test suite and downsampled to reduce its size. The original image is derived from USGS Landsat 7 ETM imagery and is licensed under the [CC0 1.0 Universal (CC0 1.0) Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/). 6 | -------------------------------------------------------------------------------- /hvplot/tests/data/RGB-red.byte.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/hvplot/tests/data/RGB-red.byte.tif -------------------------------------------------------------------------------- /hvplot/tests/plotting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holoviz/hvplot/25e6456e3fab40205f442b1df41f6422e560808f/hvplot/tests/plotting/__init__.py -------------------------------------------------------------------------------- /hvplot/tests/plotting/testandrewscurves.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import pytest 4 | 5 | from hvplot.plotting import andrews_curves 6 | 7 | 8 | @pytest.fixture 9 | def df(): 10 | return pd.DataFrame( 11 | { 12 | 'class': ['A', 'B', 'C'], 13 | 'x': [0, 2, 1], 14 | 'y': [1, 1, 2], 15 | 'z': [2, 1, 1], 16 | } 17 | ) 18 | 19 | 20 | def test_andrews_curves_x_axis_data(df): 21 | curves = andrews_curves(df, 'class') 22 | assert len(curves) == len(df) 23 | c1 = curves.get(('Curve', 'A')) 24 | assert c1.data['t'].between(-np.pi, np.pi).all() 25 | -------------------------------------------------------------------------------- /hvplot/tests/plotting/testcore.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import hvplot.pandas # noqa 4 | import pytest 5 | 6 | from hvplot import hvPlotTabular 7 | from hvplot.tests.util import makeDataFrame 8 | 9 | try: 10 | import polars as pl 11 | import hvplot.polars # noqa 12 | 13 | skip_polar = False 14 | except ImportError: 15 | 16 | class pl: 17 | DataFrame = None 18 | LazyFrame = None 19 | Series = None 20 | 21 | skip_polar = True 22 | 23 | try: 24 | import dask.dataframe as dd 25 | import hvplot.dask # noqa 26 | except ImportError: 27 | dd = None 28 | 29 | 30 | TYPES = {t for t in dir(hvPlotTabular) if not t.startswith('_') and t != 'explorer'} 31 | FRAME_TYPES = TYPES - {'bivariate', 'heatmap', 'hexbin', 'labels', 'vectorfield'} 32 | SERIES_TYPES = FRAME_TYPES - {'points', 'polygons', 'ohlc', 'paths'} 33 | frame_kinds = pytest.mark.parametrize('kind', sorted(FRAME_TYPES)) 34 | series_kinds = pytest.mark.parametrize('kind', sorted(SERIES_TYPES)) 35 | 36 | y_combinations = pytest.mark.parametrize( 37 | 'y', 38 | ( 39 | ['A', 'B', 'C', 'D'], 40 | ('A', 'B', 'C', 'D'), 41 | {'A', 'B', 'C', 'D'}, 42 | np.array(['A', 'B', 'C', 'D']), 43 | pd.Index(['A', 'B', 'C', 'D']), 44 | pd.Series(['A', 'B', 'C', 'D']), 45 | ), 46 | ids=lambda x: type(x).__name__, 47 | ) 48 | 49 | 50 | @frame_kinds 51 | @y_combinations 52 | def test_dataframe_pandas(kind, y): 53 | df = makeDataFrame() 54 | df.hvplot(y=y, kind=kind) 55 | 56 | 57 | @series_kinds 58 | def test_series_pandas(kind): 59 | ser = pd.Series(np.random.rand(10), name='A') 60 | ser.hvplot(kind=kind) 61 | 62 | 63 | @pytest.mark.skipif(dd is None, reason='dask not installed') 64 | @frame_kinds 65 | @y_combinations 66 | def test_dataframe_dask(kind, y): 67 | df = dd.from_pandas(makeDataFrame(), npartitions=2) 68 | assert isinstance(df, dd.DataFrame) 69 | df.hvplot(y=y, kind=kind) 70 | 71 | 72 | @pytest.mark.skipif(dd is None, reason='dask not installed') 73 | @series_kinds 74 | def test_series_dask(kind): 75 | ser = dd.from_pandas(pd.Series(np.random.rand(10), name='A'), npartitions=2) 76 | assert isinstance(ser, dd.Series) 77 | ser.hvplot(kind=kind) 78 | 79 | 80 | @pytest.mark.skipif(skip_polar, reason='polars not installed') 81 | @pytest.mark.parametrize('cast', (pl.DataFrame, pl.LazyFrame)) 82 | @frame_kinds 83 | @y_combinations 84 | def test_dataframe_polars(kind, y, cast): 85 | df = cast(makeDataFrame()) 86 | assert isinstance(df, cast) 87 | df.hvplot(y=y, kind=kind) 88 | 89 | 90 | @pytest.mark.skipif(skip_polar, reason='polars not installed') 91 | @series_kinds 92 | def test_series_polars(kind): 93 | ser = pl.Series(values=np.random.rand(10), name='A') 94 | assert isinstance(ser, pl.Series) 95 | ser.hvplot(kind=kind) 96 | -------------------------------------------------------------------------------- /hvplot/tests/plotting/testohlc.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import hvplot.pandas # noqa 3 | 4 | 5 | df = pd.DataFrame( 6 | { 7 | 'Open': [100.00, 101.25, 102.75], 8 | 'High': [104.10, 105.50, 110.00], 9 | 'Low': [94.00, 97.10, 99.20], 10 | 'Close': [101.15, 99.70, 109.50], 11 | 'Volume': [10012, 5000, 18000], 12 | }, 13 | index=[pd.Timestamp('2022-08-01'), pd.Timestamp('2022-08-03'), pd.Timestamp('2022-08-04')], 14 | ) 15 | 16 | ohlc_cols = ['Open', 'High', 'Low', 'Close'] 17 | 18 | 19 | def test_ohlc_hover_cols(): 20 | plot = df.hvplot.ohlc(y=ohlc_cols, hover_cols=['Volume']) 21 | segments = plot.Segments.I 22 | assert 'Volume' in segments 23 | tooltips = segments.opts.get('plot').kwargs['tools'][0].tooltips 24 | assert len(tooltips) == len(df.columns) + 1 25 | assert tooltips[-1] == ('Volume', '@Volume') 26 | 27 | 28 | def test_ohlc_hover_cols_all(): 29 | plot = df.hvplot.ohlc(y=ohlc_cols, hover_cols='all') 30 | segments = plot.Segments.I 31 | assert 'Volume' in segments 32 | tooltips = segments.opts.get('plot').kwargs['tools'][0].tooltips 33 | assert len(tooltips) == len(df.columns) + 1 34 | assert tooltips[-1] == ('Volume', '@Volume') 35 | 36 | 37 | def test_ohlc_date_tooltip_format(): 38 | plot = df.hvplot.ohlc(y=ohlc_cols) 39 | segments = plot.Segments.I 40 | hover_tool = segments.opts.get('plot').kwargs['tools'][0] 41 | tooltips = hover_tool.tooltips 42 | x_label, x_tooltip = tooltips[0] 43 | assert '{%F %T}' in x_tooltip 44 | formatter_key = '@' + x_label 45 | formatter = hover_tool.formatters 46 | assert formatter[formatter_key] == 'datetime' 47 | 48 | 49 | def test_ohlc_non_datetime_x_axis(): 50 | df = pd.DataFrame( 51 | { 52 | 'Open': [100.00, 101.25, 102.75], 53 | 'High': [104.10, 105.50, 110.00], 54 | 'Low': [94.00, 97.10, 99.20], 55 | 'Close': [101.15, 99.70, 109.50], 56 | 'Volume': [10012, 5000, 18000], 57 | }, 58 | index=[1, 2, 3], 59 | ) 60 | 61 | ohlc_cols = ['Open', 'High', 'Low', 'Close'] 62 | 63 | plot = df.hvplot.ohlc(y=ohlc_cols) 64 | segments = plot.Segments.I 65 | hover_tool = segments.opts.get('plot').kwargs['tools'][0] 66 | tooltips = hover_tool.tooltips 67 | x_label, x_tooltip = tooltips[0] 68 | assert '{%F}' not in x_tooltip 69 | formatter_key = '@' + x_label 70 | assert formatter_key not in hover_tool.formatters 71 | 72 | 73 | def test_ohlc_non_index_date_col(): 74 | df = pd.DataFrame( 75 | { 76 | 'Date': [ 77 | pd.Timestamp('2022-08-01'), 78 | pd.Timestamp('2022-08-03'), 79 | pd.Timestamp('2022-08-04'), 80 | ], 81 | 'Open': [100.00, 101.25, 102.75], 82 | 'High': [104.10, 105.50, 110.00], 83 | 'Low': [94.00, 97.10, 99.20], 84 | 'Close': [101.15, 99.70, 109.50], 85 | 'Volume': [10012, 5000, 18000], 86 | }, 87 | ) 88 | plot = df.hvplot.ohlc(hover_cols='all', use_index=False) 89 | segments = plot.Segments.I 90 | hover_tool = segments.opts.get('plot').kwargs['tools'][0] 91 | tooltips = hover_tool.tooltips 92 | assert len(tooltips) == len(df.columns) 93 | assert tooltips[0] == ('Date', '@Date{%F %T}') 94 | -------------------------------------------------------------------------------- /hvplot/tests/test_links.py: -------------------------------------------------------------------------------- 1 | """Urls in docstrings etc. should be valid and secure, i.e. 2 | 3 | - exist, i.e. provide a 200 response 4 | - use https:// instead of http:// unless 5 | - https:// is not supported by the web site 6 | - https:// cannot be used. For example in SVGs. 7 | """ 8 | 9 | import pathlib 10 | import re 11 | from concurrent.futures import ThreadPoolExecutor, as_completed 12 | from urllib.request import urlopen 13 | import glob 14 | 15 | import pytest 16 | 17 | # Note: The regex will find urls from code cells in notebooks ending with '\\' because the are really inside \"some_url\" 18 | URL_REGEX = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))" # pylint: disable=line-too-long 19 | ROOT = pathlib.Path(__file__).parent 20 | PACKAGE_ROOT = ROOT.parent 21 | MAX_WORKERS = 10 22 | POST_FIXES = ['.py', '.ipynb', '.md', '.yaml'] 23 | SKIP_URLS = [ 24 | 'https://anaconda.org/anaconda/hvplot', 25 | 'https://anaconda.org/conda-forge/hvplot', 26 | 'https://anaconda.org/pyviz/hvplot', 27 | 'https://creativecommons.org/publicdomain/zero/1.0/', 28 | 'https://github.com/rasterio/rasterio', 29 | 'https://www.dask.org', 30 | 'pyproject.toml/equivalent', 31 | ] 32 | 33 | 34 | def _get_files_to_check(): 35 | for post_fix in POST_FIXES: 36 | for file in glob.glob('**/*' + post_fix, recursive=True): 37 | yield pathlib.Path(file) 38 | 39 | 40 | FIXTURES = [pytest.param(file, id=str(file)) for file in _get_files_to_check()] 41 | 42 | 43 | def _skip_url(url: str): 44 | if url in SKIP_URLS: 45 | return True 46 | if url.startswith('https://github.com/holoviz/hvplot/pull/'): 47 | return True 48 | if url.startswith('https://img.shields.io'): 49 | return True 50 | if url.startswith('assets.holoviews.org/data/'): 51 | return True 52 | if url.startswith('Math.PI'): 53 | return True 54 | return False 55 | 56 | 57 | def _clean_url(url: str): 58 | if url.endswith('\\'): 59 | return url[0:-1] 60 | return url 61 | 62 | 63 | def _find_urls(text): 64 | url = re.findall(URL_REGEX, text) 65 | return {_clean_url(x[0]) for x in url if not _skip_url(x[0])} 66 | 67 | 68 | def _request_a_response(url): 69 | return urlopen(url) 70 | 71 | 72 | def _verify_urls(urls): 73 | """Returns True if all urls are valid""" 74 | futures = {} 75 | with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: 76 | futures = {} 77 | for url in urls: 78 | futures[executor.submit(_request_a_response, url)] = url 79 | 80 | for future in as_completed(futures): 81 | url = futures[future] 82 | try: 83 | result = future.result() 84 | except Exception as ex: 85 | raise ValueError(f'The url {url} raised an exception') from ex 86 | if not result.status == 200: 87 | raise ValueError(f'The url {url} responded with status {result.status}, not 200.') 88 | 89 | return True 90 | 91 | 92 | # @pytest.mark.parametrize(["file"], FIXTURES) 93 | # def test_urls(file: pathlib.Path): 94 | # """The urls is docstring should be valid""" 95 | # # Given 96 | # text = file.read_text() 97 | # urls = _find_urls(text) 98 | # # When/ Then 99 | # assert _verify_urls(urls) 100 | -------------------------------------------------------------------------------- /hvplot/tests/testbackend_transforms.py: -------------------------------------------------------------------------------- 1 | import holoviews 2 | import pytest 3 | from holoviews.core import Store 4 | from holoviews.element import Area, Curve 5 | 6 | from hvplot.backend_transforms import ( 7 | _transfer_opts, 8 | _transform_size_to_mpl, 9 | _is_interactive_opt, 10 | ) 11 | 12 | 13 | @pytest.mark.parametrize( 14 | ('width', 'height', 'aspect', 'opts'), 15 | ( 16 | (300, 100, None, {'aspect': 3.0, 'fig_size': 100.0}), 17 | (300, None, 3, {'aspect': 3, 'fig_size': 100.0}), 18 | (None, 300, 3, {'aspect': 3, 'fig_size': 100.0}), 19 | (300, None, None, {'fig_size': 100.0}), 20 | (None, 300, None, {'fig_size': 100.0}), 21 | ), 22 | ) 23 | def test_transform_size_to_mpl(width, height, aspect, opts): 24 | assert _transform_size_to_mpl(width, height, aspect) == opts 25 | 26 | 27 | @pytest.mark.parametrize( 28 | ('element', 'opt', 'val', 'backend', 'opt_kind', 'transf_opt', 'transf_val'), 29 | ( 30 | (Curve([]), 'line_dash', 'dashed', 'matplotlib', 'style', 'linestyle', 'dashed'), 31 | (Curve([]), 'line_alpha', 0.123, 'matplotlib', 'style', None, None), 32 | (Area([]), 'line_cap', 'square', 'matplotlib', 'style', 'capstyle', 'projecting'), 33 | (Curve([]), 'line_dash', 'dashed', 'plotly', 'style', 'dash', 'dash'), 34 | ), 35 | ) 36 | def test_transfer_opts(element, opt, val, backend, opt_kind, transf_opt, transf_val): 37 | current_backend = Store.current_backend 38 | if backend not in Store.registry: 39 | holoviews.extension(backend) 40 | Store.set_current_backend(backend) 41 | try: 42 | element = element.opts(backend='bokeh', **{opt: val}) 43 | new_element = element.apply(_transfer_opts, backend=backend) 44 | new_opts = new_element.opts.get(opt_kind).kwargs 45 | if transf_opt is None: 46 | assert val not in new_opts.values() 47 | else: 48 | assert transf_opt in new_opts 49 | assert new_opts[transf_opt] == transf_val 50 | finally: 51 | Store.set_current_backend(current_backend) 52 | 53 | 54 | @pytest.mark.parametrize( 55 | ('opt', 'val', 'backend', 'opt_kind', 'transf_opt', 'transf_val'), 56 | ( 57 | ('line_dash', 'dashed', 'matplotlib', 'style', 'linestyle', 'dashed'), 58 | ('line_dash', 'dashed', 'plotly', 'style', 'dash', 'dash'), 59 | ), 60 | ) 61 | def test_transfer_opts_compositeoverlay(opt, val, backend, opt_kind, transf_opt, transf_val): 62 | current_backend = Store.current_backend 63 | if backend not in Store.registry: 64 | holoviews.extension(backend) 65 | Store.set_current_backend(backend) 66 | try: 67 | element = Area([]) * Curve([]).opts(backend='bokeh', **{opt: val}) 68 | new_element = element.apply(_transfer_opts, backend=backend) 69 | transformed_element = new_element.Curve.I 70 | new_opts = transformed_element.opts.get(opt_kind).kwargs 71 | assert transf_opt in new_opts 72 | assert new_opts[transf_opt] == transf_val 73 | finally: 74 | Store.set_current_backend(current_backend) 75 | 76 | 77 | @pytest.mark.parametrize( 78 | ('bk_option', 'expected'), 79 | ( 80 | ('height', False), 81 | ('hover_line_alpha', True), 82 | ('nonselection_line_alpha', True), 83 | ('muted_line_alpha', True), 84 | ('selection_line_alpha', True), 85 | ('annular_muted_alpha', True), 86 | ), 87 | ) 88 | def test_is_interactive_opt(bk_option, expected): 89 | assert _is_interactive_opt(bk_option) == expected 90 | -------------------------------------------------------------------------------- /hvplot/tests/testdeprecations.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for deprecation warnings. 3 | """ 4 | 5 | import pandas as pd 6 | import pytest 7 | 8 | from hvplot.converter import HoloViewsConverter 9 | from hvplot.plotting import plot 10 | from hvplot.tests.util import makeDataFrame 11 | 12 | 13 | def test_converter_argument_debug(disable_param_warnings_as_exceptions): 14 | df = pd.DataFrame({'x': [0, 1], 'y': [0, 1]}) 15 | with pytest.warns(FutureWarning): 16 | HoloViewsConverter(df, 'x', 'y', debug=True) 17 | 18 | 19 | def test_plotting_plot_duckdb(): 20 | duckdb = pytest.importorskip('duckdb') 21 | connection = duckdb.connect(':memory:') 22 | relation = duckdb.from_df(makeDataFrame(), connection=connection) 23 | with pytest.warns(FutureWarning): 24 | plot(relation, 'line') 25 | -------------------------------------------------------------------------------- /hvplot/tests/testdocstring.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | 3 | import pytest 4 | 5 | pytest.importorskip('numpydoc') 6 | 7 | from hvplot.converter import HoloViewsConverter # noqa: E402 8 | from hvplot.util import _get_docstring_group_parameters # noqa: E402 9 | 10 | 11 | @pytest.mark.parametrize('section', HoloViewsConverter._docstring_sections.values()) 12 | def test_docstring_converter_sections_present(section): 13 | assert section in HoloViewsConverter.__doc__ 14 | 15 | 16 | @pytest.mark.parametrize('section', HoloViewsConverter._docstring_sections.values()) 17 | def test_docstring_converter_sections_include_parameters(section): 18 | assert _get_docstring_group_parameters(section) 19 | 20 | 21 | def parse_docstring_for_param_names(section_title): 22 | parameters = _get_docstring_group_parameters(section_title) 23 | parameter_names = [] 24 | for param in parameters: 25 | sparams = param.name.split('/') 26 | parameter_names.extend(sparams) 27 | return parameter_names 28 | 29 | 30 | @pytest.mark.parametrize( 31 | 'section, options', 32 | [(k, v) for k, v in HoloViewsConverter._options_groups.items()], 33 | ) 34 | def test_docstring_converter_options_match_per_section(section, options): 35 | section_title = HoloViewsConverter._docstring_sections[section] 36 | parameter_names = parse_docstring_for_param_names(section_title) 37 | assert set(options) == set(parameter_names) 38 | 39 | 40 | def test_docstring_converter_no_duplicate_and_match_options(): 41 | all_doc_params = [] 42 | for section_title in HoloViewsConverter._docstring_sections.values(): 43 | params = parse_docstring_for_param_names(section_title) 44 | all_doc_params.extend(params) 45 | 46 | assert len(all_doc_params) == len(set(all_doc_params)) 47 | 48 | all_options = list(itertools.chain(*HoloViewsConverter._options_groups.values())) 49 | 50 | assert len(all_options) == len(set(all_options)) 51 | 52 | assert set(all_doc_params) == set(all_options) 53 | -------------------------------------------------------------------------------- /hvplot/tests/testfugue.py: -------------------------------------------------------------------------------- 1 | """Fugue test suite""" 2 | 3 | import hvplot 4 | import pandas as pd 5 | import pytest 6 | 7 | # Patch required before importing hvplot.fugue 8 | hvplot.util._fugue_ipython = True 9 | 10 | try: 11 | import fugue.api as fa 12 | import fugue_sql_antlr # noqa: F401 13 | import hvplot.fugue # noqa: F401 14 | except ImportError: 15 | pytest.skip(allow_module_level=True) 16 | 17 | 18 | @pytest.fixture 19 | def table(): 20 | df = pd.DataFrame( 21 | { 22 | 'g': ['a', 'b', 'a', 'b', 'a', 'b'], 23 | 'x': [1, 2, 3, 4, 5, 6], 24 | 'y': [1, 2, 3, 4, 5, 6], 25 | } 26 | ) 27 | return df 28 | 29 | 30 | def test_fugure_ipython_line(table, capsys): 31 | """hvplot works with Fugue""" 32 | fa.fugue_sql( 33 | """ 34 | OUTPUT table USING hvplot:line( 35 | x="x", 36 | y="y", 37 | by="g", 38 | size=100, 39 | opts={"width": 500, "height": 500} 40 | ) 41 | """ 42 | ) 43 | # Check that the output contains the following: 44 | # Column 45 | # [0] HoloViews(NdOverlay) 46 | output = capsys.readouterr().out 47 | assert output == 'Column\n [0] HoloViews(NdOverlay)\n' 48 | -------------------------------------------------------------------------------- /hvplot/tests/testgeowithoutgv.py: -------------------------------------------------------------------------------- 1 | """ 2 | Geo tests **without** importing GeoViews. 3 | """ 4 | 5 | import holoviews as hv 6 | import hvplot.pandas # noqa 7 | import numpy as np 8 | import pandas as pd 9 | import pytest 10 | 11 | from hvplot.util import is_geodataframe 12 | 13 | try: 14 | import dask.dataframe as dd 15 | import hvplot.dask # noqa 16 | except ImportError: 17 | dd = None 18 | 19 | try: 20 | import spatialpandas as spd 21 | except ModuleNotFoundError: 22 | spd = None 23 | 24 | 25 | bk_renderer = hv.Store.renderers['bokeh'] 26 | 27 | 28 | @pytest.fixture 29 | def simple_df(): 30 | return pd.DataFrame(np.random.rand(10, 2), columns=['x', 'y']) 31 | 32 | 33 | class TestAnnotationNotGeo: 34 | def test_plot_tiles_doesnt_set_geo(self, simple_df): 35 | plot = simple_df.hvplot.points('x', 'y', tiles=True) 36 | assert len(plot) == 2 37 | assert isinstance(plot.get(0), hv.Tiles) 38 | assert 'openstreetmap' in plot.get(0).data 39 | assert 'x_' in plot.get(1).data 40 | assert 'y_' in plot.get(1).data 41 | bk_plot = bk_renderer.get_plot(plot) 42 | assert bk_plot.projection == 'mercator' 43 | 44 | def test_plot_specific_tiles_doesnt_set_geo(self, simple_df): 45 | plot = simple_df.hvplot.points('x', 'y', tiles='ESRI') 46 | assert len(plot) == 2 47 | assert isinstance(plot.get(0), hv.Tiles) 48 | assert 'ArcGIS' in plot.get(0).data 49 | assert 'x_' in plot.get(1).data 50 | assert 'y_' in plot.get(1).data 51 | bk_plot = bk_renderer.get_plot(plot) 52 | assert bk_plot.projection == 'mercator' 53 | 54 | def test_plot_with_specific_tile_class(self, simple_df): 55 | plot = simple_df.hvplot.points('x', 'y', tiles=hv.element.tiles.EsriImagery) 56 | assert len(plot) == 2 57 | assert isinstance(plot.get(0), hv.Tiles) 58 | assert 'ArcGIS' in plot.get(0).data 59 | bk_plot = bk_renderer.get_plot(plot) 60 | assert bk_plot.projection == 'mercator' 61 | 62 | def test_plot_with_specific_tile_obj(self, simple_df): 63 | plot = simple_df.hvplot.points('x', 'y', tiles=hv.element.tiles.EsriImagery()) 64 | assert len(plot) == 2 65 | assert isinstance(plot.get(0), hv.Tiles) 66 | assert 'ArcGIS' in plot.get(0).data 67 | assert 'x_' in plot.get(1).data 68 | assert 'y_' in plot.get(1).data 69 | bk_plot = bk_renderer.get_plot(plot) 70 | assert bk_plot.projection == 'mercator' 71 | 72 | def test_plot_with_xyzservices_tileprovider(self, simple_df): 73 | xyzservices = pytest.importorskip('xyzservices') 74 | plot = simple_df.hvplot.points('x', 'y', tiles=xyzservices.providers.Esri.WorldImagery) 75 | assert 'x_' in plot.get(1).data 76 | assert 'y_' in plot.get(1).data 77 | assert len(plot) == 2 78 | assert isinstance(plot.get(0), hv.Tiles) 79 | assert isinstance(plot.get(0).data, xyzservices.TileProvider) 80 | bk_plot = bk_renderer.get_plot(plot) 81 | assert bk_plot.projection == 'mercator' 82 | 83 | @pytest.mark.skipif(dd is None, reason='dask not installed') 84 | def test_plot_with_dask(self, simple_df): 85 | ddf = dd.from_pandas(simple_df, npartitions=2) 86 | plot = ddf.hvplot.points('x', 'y', tiles=True) 87 | assert 'x_' not in plot.get(1).data 88 | assert 'y_' not in plot.get(1).data 89 | assert len(plot) == 2 90 | assert isinstance(plot.get(0), hv.Tiles) 91 | bk_plot = bk_renderer.get_plot(plot) 92 | assert bk_plot.projection == 'mercator' 93 | 94 | @pytest.mark.skipif(spd is None, reason='spatialpandas not installed') 95 | def test_plot_without_crs(self): 96 | square = spd.geometry.Polygon([(0.0, 0), (0, 1), (1, 1), (1, 0)]) 97 | sdf = spd.GeoDataFrame({'geometry': spd.GeoSeries([square, square]), 'name': ['A', 'B']}) 98 | plot = sdf.hvplot.polygons(tiles=True) 99 | 100 | assert len(plot) == 2 101 | assert is_geodataframe(sdf) 102 | assert not hasattr(sdf, 'crs') 103 | assert isinstance(plot.get(0), hv.Tiles) 104 | assert isinstance(plot.get(1), hv.Polygons) 105 | bk_plot = bk_renderer.get_plot(plot) 106 | assert bk_plot.projection == 'mercator' # projection enabled due to `tiles=True` 107 | -------------------------------------------------------------------------------- /hvplot/tests/testhelp.py: -------------------------------------------------------------------------------- 1 | import hvplot.pandas 2 | import pytest 3 | 4 | from holoviews.core import Store 5 | from holoviews.element import Curve 6 | 7 | from hvplot.util import _get_doc_and_signature 8 | 9 | 10 | @pytest.fixture 11 | def reset_default_backend(): 12 | yield 13 | hvplot.extension('bokeh') 14 | hvplot.extension.compatibility = None 15 | 16 | 17 | def test_help_style_extension_output(reset_default_backend): 18 | # default, after e.g. import hvplot.pandas 19 | docstring, signature = _get_doc_and_signature( 20 | cls=hvplot.hvPlot, 21 | kind='line', 22 | completions=False, 23 | docstring=False, 24 | generic=False, 25 | style=True, 26 | signature=None, 27 | ) 28 | assert docstring == '\nStyling options\n---------------\n' + '\n'.join( 29 | sorted(Store.registry['bokeh'][Curve].style_opts) 30 | ) 31 | 32 | # The current backend becomes matplotlib 33 | hvplot.extension('matplotlib', 'plotly') 34 | docstring, signature = _get_doc_and_signature( 35 | cls=hvplot.hvPlot, 36 | kind='line', 37 | completions=False, 38 | docstring=False, 39 | generic=False, 40 | style=True, 41 | signature=None, 42 | ) 43 | assert docstring == '\nStyling options\n---------------\n' + '\n'.join( 44 | sorted(Store.registry['matplotlib'][Curve].style_opts) 45 | ) 46 | 47 | # The current backend becomes plotly 48 | hvplot.output(backend='plotly') 49 | docstring, signature = _get_doc_and_signature( 50 | cls=hvplot.hvPlot, 51 | kind='line', 52 | completions=False, 53 | docstring=False, 54 | generic=False, 55 | style=True, 56 | signature=None, 57 | ) 58 | assert docstring == '\nStyling options\n---------------\n' + '\n'.join( 59 | sorted(Store.registry['plotly'][Curve].style_opts) 60 | ) 61 | 62 | 63 | @pytest.mark.usefixtures('disable_param_warnings_as_exceptions') 64 | def test_help_style_compatibility(reset_default_backend): 65 | # The current backend is plotly but the style options are those of matplotlib 66 | hvplot.extension('plotly', 'matplotlib', compatibility='matplotlib') 67 | docstring, signature = _get_doc_and_signature( 68 | cls=hvplot.hvPlot, 69 | kind='line', 70 | completions=False, 71 | docstring=False, 72 | generic=False, 73 | style=True, 74 | signature=None, 75 | ) 76 | assert docstring == '\nStyling options\n---------------\n' + '\n'.join( 77 | sorted(Store.registry['matplotlib'][Curve].style_opts) 78 | ) 79 | -------------------------------------------------------------------------------- /hvplot/tests/testibis.py: -------------------------------------------------------------------------------- 1 | """Basic ibis tests""" 2 | 3 | import numpy as np 4 | import pandas as pd 5 | import pytest 6 | 7 | try: 8 | import hvplot.ibis # noqa 9 | import ibis 10 | except ImportError: 11 | pytest.skip(allow_module_level=True) 12 | 13 | 14 | def test_ibis_hist(): 15 | df = pd.DataFrame(dict(x=np.arange(10))) 16 | table = ibis.memtable(df) 17 | table.hvplot.hist('x') 18 | -------------------------------------------------------------------------------- /hvplot/tests/testnetworkx.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, SkipTest 2 | 3 | try: 4 | import numpy as np 5 | import networkx as nx 6 | import hvplot.networkx as hvnx 7 | except ImportError: 8 | raise SkipTest('NetworkX not available') 9 | 10 | 11 | class TestOptions(TestCase): 12 | def setUp(self): 13 | # Create nodes (1-10) in unsorted order 14 | nodes = np.array([1, 4, 5, 10, 8, 9, 3, 7, 2, 6]) 15 | edges = list(zip(nodes[:-1], nodes[1:])) 16 | 17 | g = nx.Graph() 18 | g.add_nodes_from(nodes) 19 | g.add_edges_from(edges) 20 | 21 | self.nodes = nodes 22 | self.g = g 23 | 24 | def test_nodes_are_not_sorted(self): 25 | plot = hvnx.draw(self.g) 26 | assert all(self.nodes == plot.nodes.dimension_values(2)) 27 | 28 | def test_default_hover_tooltip(self): 29 | from bokeh.models import HoverTool 30 | 31 | plot = hvnx.draw(self.g) 32 | hover = next(t for t in plot.opts['tools'] if isinstance(t, HoverTool)) 33 | assert [('index', '@{index_hover}')] == hover.tooltips 34 | -------------------------------------------------------------------------------- /hvplot/tests/testoverrides.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import numpy as np 4 | import pandas as pd 5 | import pytest 6 | import xarray as xr 7 | 8 | from hvplot.plotting import hvPlot, hvPlotTabular 9 | from holoviews import Store, Scatter 10 | from holoviews.element.comparison import ComparisonTestCase 11 | 12 | 13 | class TestOverrides(ComparisonTestCase): 14 | def setUp(self): 15 | import hvplot.pandas # noqa 16 | 17 | self.df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['x', 'y']) 18 | 19 | def test_define_default_options(self): 20 | hvplot = hvPlotTabular(self.df, width=42, height=42) 21 | curve = hvplot(y='y') 22 | opts = Store.lookup_options('bokeh', curve, 'plot') 23 | self.assertEqual(opts.options.get('width'), 42) 24 | self.assertEqual(opts.options.get('height'), 42) 25 | 26 | def test_define_custom_method(self): 27 | hvplot = hvPlotTabular(self.df, {'custom_scatter': {'width': 42, 'height': 42}}) 28 | custom_scatter = hvplot.custom_scatter(y='y') 29 | scatter = hvplot.scatter(y='y') 30 | custom_opts = Store.lookup_options('bokeh', custom_scatter, 'plot') 31 | opts = Store.lookup_options('bokeh', scatter, 'plot') 32 | self.assertEqual(custom_opts.options.get('width'), 42) 33 | self.assertEqual(custom_opts.options.get('height'), 42) 34 | self.assertNotEqual(opts.options.get('width'), 42) 35 | self.assertNotEqual(opts.options.get('height'), 42) 36 | 37 | def test_define_customize_method(self): 38 | hvplot = hvPlotTabular(self.df, {'scatter': {'width': 42, 'height': 42}}) 39 | custom_scatter = hvplot.scatter(y='y') 40 | curve = hvplot.line(y='y') 41 | custom_opts = Store.lookup_options('bokeh', custom_scatter, 'plot') 42 | opts = Store.lookup_options('bokeh', curve, 'plot') 43 | self.assertEqual(custom_opts.options.get('width'), 42) 44 | self.assertEqual(custom_opts.options.get('height'), 42) 45 | self.assertNotEqual(opts.options.get('width'), 42) 46 | self.assertNotEqual(opts.options.get('height'), 42) 47 | 48 | @pytest.mark.usefixtures('disable_param_warnings_as_exceptions') 49 | def test_attempt_to_override_kind_on_method(self): 50 | hvplot = hvPlotTabular(self.df, {'scatter': {'kind': 'line'}}) 51 | self.assertIsInstance(hvplot.scatter(y='y'), Scatter) 52 | 53 | def test_pandas_query_metadata(self): 54 | hvplot = hvPlotTabular(self.df, query='x>2') 55 | assert len(hvplot._data) == 2 56 | 57 | 58 | class TestXArrayOverrides(ComparisonTestCase): 59 | def setUp(self): 60 | coords = OrderedDict([('time', [0, 1]), ('lat', [0, 1]), ('lon', [0, 1])]) 61 | self.da_img_by_time = xr.DataArray( 62 | np.arange(8).reshape((2, 2, 2)), coords, ['time', 'lat', 'lon'] 63 | ).assign_coords(lat1=xr.DataArray([2, 3], dims=['lat'])) 64 | 65 | def test_xarray_isel_scalar_metadata(self): 66 | hvplot = hvPlot(self.da_img_by_time, isel={'time': 1}) 67 | assert hvplot._data.ndim == 2 68 | 69 | def test_xarray_isel_nonscalar_metadata(self): 70 | hvplot = hvPlot(self.da_img_by_time, isel={'time': [1]}) 71 | assert hvplot._data.ndim == 3 72 | assert len(hvplot._data.time) == 1 73 | 74 | def test_xarray_sel_metadata(self): 75 | hvplot = hvPlot(self.da_img_by_time, sel={'time': 1}) 76 | assert hvplot._data.ndim == 2 77 | -------------------------------------------------------------------------------- /hvplot/tests/testpanel.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for panel widgets and param objects as arguments 3 | """ 4 | 5 | from unittest import TestCase 6 | 7 | import panel as pn 8 | 9 | from hvplot.util import process_xarray # noqa 10 | 11 | 12 | def look_for_class(panel, classname, items=None): 13 | """ 14 | Descend a panel object and find any instances of the given class 15 | """ 16 | if items is None: 17 | items = [] 18 | if isinstance(panel, pn.layout.ListPanel): 19 | for p in panel: 20 | items = look_for_class(p, classname, items) 21 | elif isinstance(panel, classname): 22 | items.append(panel) 23 | return items 24 | 25 | 26 | class TestPanelObjects(TestCase): 27 | def setUp(self): 28 | import hvplot.pandas # noqa 29 | from bokeh.sampledata.iris import flowers 30 | 31 | self.flowers = flowers 32 | self.cols = list(self.flowers.columns[:-1]) 33 | 34 | def test_using_explicit_widgets_works(self): 35 | x = pn.widgets.Select(name='x', value='sepal_length', options=self.cols) 36 | y = pn.widgets.Select(name='y', value='sepal_width', options=self.cols) 37 | kind = pn.widgets.Select(name='kind', value='scatter', options=['bivariate', 'scatter']) 38 | by_species = pn.widgets.Checkbox(name='By species') 39 | color = pn.widgets.ColorPicker(value='#ff0000') 40 | 41 | @pn.depends(by_species.param.value, color.param.value) 42 | def by_species_fn(by_species, color): 43 | return 'species' if by_species else color 44 | 45 | self.flowers.hvplot(x, y=y, kind=kind.param.value, c=color) 46 | 47 | def test_casting_widgets_to_different_classes(self): 48 | pane = self.flowers.hvplot.scatter( 49 | groupby='species', legend='top_right', widgets={'species': pn.widgets.DiscreteSlider} 50 | ) 51 | 52 | assert len(look_for_class(pane, pn.widgets.DiscreteSlider)) == 1 53 | 54 | def test_using_explicit_widgets_with_groupby_does_not_raise_error(self): 55 | x = pn.widgets.Select(name='x', value='sepal_length', options=self.cols) 56 | y = pn.widgets.Select(name='y', value='sepal_width', options=self.cols) 57 | 58 | pane = self.flowers.hvplot(x, y, groupby='species') 59 | assert isinstance(pane, pn.param.ParamFunction) 60 | -------------------------------------------------------------------------------- /hvplot/tests/testpatchsignature.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | 5 | from hvplot.converter import HoloViewsConverter 6 | from hvplot.util import _PatchHvplotDocstrings, _in_ipython, _parse_docstring_sections 7 | 8 | 9 | def run_script(script, env_vars=None): 10 | env_vars = env_vars or {} 11 | process = subprocess.run( 12 | [sys.executable, '-c', script], 13 | text=True, 14 | capture_output=True, 15 | env=os.environ | env_vars, 16 | ) 17 | if process.returncode != 0: 18 | raise RuntimeError(f'Subprocess failed: {process.stderr}') 19 | return process.stdout.strip() 20 | 21 | 22 | def test_no_automatic_patching(): 23 | script = """ 24 | import inspect 25 | from hvplot import hvPlot 26 | 27 | print(inspect.signature(hvPlot.line)) 28 | """ 29 | assert not _in_ipython() 30 | out = run_script(script) 31 | assert out == '(self, x=None, y=None, **kwds)' 32 | 33 | 34 | def test_no_automatic_patching_extension_import(): 35 | script = """ 36 | import inspect 37 | import hvplot.pandas 38 | 39 | print(inspect.signature(hvplot.hvPlot.line)) 40 | """ 41 | assert not _in_ipython() 42 | out = run_script(script) 43 | assert out == '(self, x=None, y=None, **kwds)' 44 | 45 | 46 | def test_patching_env_var(): 47 | script = """ 48 | import inspect 49 | from hvplot import hvPlot 50 | 51 | print(inspect.signature(hvPlot.line)) 52 | """ 53 | assert not _in_ipython() 54 | out = run_script(script, {'HVPLOT_PATCH_PLOT_DOCSTRING_SIGNATURE': 'true'}) 55 | assert out != '(self, x=None, y=None, **kwds)' 56 | assert 'xlim' in out 57 | 58 | 59 | def test_patch_hvplot_docstrings(): 60 | patchd = _PatchHvplotDocstrings() 61 | assert patchd.orig 62 | try: 63 | patchd() 64 | for (cls, _kind), (osig, odoc) in patchd.orig.items(): 65 | obj = getattr(cls, _kind) 66 | assert obj.__signature__ != osig 67 | assert obj.__doc__ != odoc 68 | finally: 69 | patchd.reset() 70 | for (cls, _kind), (osig, odoc) in patchd.orig.items(): 71 | obj = getattr(cls, _kind) 72 | assert obj.__signature__ == osig 73 | assert obj.__doc__ == odoc 74 | 75 | 76 | def test_converter_docstrings_sections(): 77 | sections = _parse_docstring_sections(HoloViewsConverter.__doc__) 78 | assert set(sections) == set(HoloViewsConverter._docstring_sections.values()) 79 | 80 | 81 | def test_converter_options_docstrings(): 82 | assert ( 83 | HoloViewsConverter._docstring_sections.keys() == HoloViewsConverter._options_groups.keys() 84 | ) 85 | -------------------------------------------------------------------------------- /hvplot/tests/teststatplots.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import xarray as xr 4 | 5 | from holoviews import Store 6 | 7 | import hvplot.xarray # noqa: F401 8 | 9 | 10 | def test_violin_from_xarray_with_by_and_color(): 11 | latitudes = np.linspace(-90, 90, 180) 12 | longitudes = np.linspace(-180, 180, 360) 13 | times = pd.date_range('2023-01-01', periods=365, freq='D') 14 | data = np.random.random((365, 180, 360)) 15 | da = xr.DataArray( 16 | data, 17 | coords={'time': times, 'lat': latitudes, 'lon': longitudes}, 18 | dims=['time', 'lat', 'lon'], 19 | name='temperature', 20 | ) 21 | plot = da.hvplot.violin(y='temperature', by='lat', color='lat') 22 | assert plot.kdims == ['lat'] 23 | opts = Store.lookup_options('bokeh', plot, 'style') 24 | assert opts.kwargs['violin_fill_color'] == 'lat' 25 | -------------------------------------------------------------------------------- /hvplot/tests/teststreaming.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import pandas as pd 4 | 5 | from holoviews.streams import Buffer, Pipe 6 | 7 | 8 | class TestExplicitStreamPlotting(TestCase): 9 | def setUp(self): 10 | import hvplot.pandas # noqa 11 | 12 | self.df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['x', 'y']) 13 | 14 | def test_pipe_stream(self): 15 | stream = Pipe(data=self.df) 16 | plot = self.df.hvplot('x', 'y', stream=stream) 17 | pd.testing.assert_frame_equal(plot[()].data, self.df) 18 | new_df = pd.DataFrame([[7, 8], [9, 10]], columns=['x', 'y']) 19 | stream.send(new_df) 20 | pd.testing.assert_frame_equal(plot[()].data, new_df) 21 | 22 | def test_buffer_stream(self): 23 | stream = Buffer(data=self.df, index=False) 24 | plot = self.df.hvplot('x', 'y', stream=stream) 25 | pd.testing.assert_frame_equal(plot[()].data, self.df) 26 | new_df = pd.DataFrame([[7, 8], [9, 10]], columns=['x', 'y']) 27 | stream.send(new_df) 28 | pd.testing.assert_frame_equal(plot[()].data, pd.concat([self.df, new_df])) 29 | -------------------------------------------------------------------------------- /hvplot/tests/testtransforms.py: -------------------------------------------------------------------------------- 1 | from unittest import SkipTest 2 | 3 | import holoviews as hv 4 | import numpy as np 5 | import pandas as pd 6 | 7 | from holoviews.element.comparison import ComparisonTestCase 8 | 9 | 10 | class TestPandasTransforms(ComparisonTestCase): 11 | def setUp(self): 12 | import hvplot.pandas # noqa 13 | 14 | def test_pandas_transform(self): 15 | demo_df = pd.DataFrame({'value': np.random.randn(50), 'probability': np.random.rand(50)}) 16 | percent = hv.dim('probability') * 100 17 | scatter = demo_df.hvplot.scatter( 18 | x='value', y='probability', transforms=dict(probability=percent) 19 | ) 20 | self.assertEqual((scatter.data['probability']).values, demo_df['probability'].values * 100) 21 | 22 | 23 | class TestXArrayTransforms(ComparisonTestCase): 24 | def setUp(self): 25 | try: 26 | import xarray as xr # noqa 27 | except ImportError: 28 | raise SkipTest('xarray not available') 29 | import hvplot.xarray # noqa 30 | 31 | def test_xarray_transform(self): 32 | import xarray as xr 33 | 34 | data = np.arange(0, 60).reshape(6, 10) 35 | x = np.arange(10) 36 | y = np.arange(6) 37 | da = xr.DataArray(data, coords={'y': y, 'x': x}, dims=('y', 'x'), name='value') 38 | img = da.hvplot.image(transforms=dict(value=hv.dim('value') * 10)) 39 | self.assertEqual(img.data.value.data, da.data * 10) 40 | -------------------------------------------------------------------------------- /hvplot/tests/util.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | from datetime import datetime 4 | 5 | import numpy as np 6 | import pandas as pd 7 | 8 | 9 | # Pandas removed its make<> test utilities in version 2.2.0. 10 | 11 | _N = 30 12 | _K = 4 13 | 14 | 15 | def getCols(k): 16 | return string.ascii_uppercase[:k] 17 | 18 | 19 | def rands_array(nchars, size, dtype='O', replace=True): 20 | """ 21 | Generate an array of byte strings. 22 | """ 23 | chars = np.array(list(string.ascii_letters + string.digits), dtype=(np.str_, 1)) 24 | retval = ( 25 | np.random.default_rng(2) 26 | .choice(chars, size=nchars * np.prod(size), replace=replace) 27 | .view((np.str_, nchars)) 28 | .reshape(size) 29 | ) 30 | return retval.astype(dtype) 31 | 32 | 33 | def makeStringIndex(k=10, name=None): 34 | return pd.Index(rands_array(nchars=10, size=k), name=name) 35 | 36 | 37 | def makeMixedDataFrame(): 38 | data = { 39 | 'A': [0.0, 1.0, 2.0, 3.0, 4.0], 40 | 'B': [0.0, 1.0, 0.0, 1.0, 0.0], 41 | 'C': ['foo1', 'foo2', 'foo3', 'foo4', 'foo5'], 42 | 'D': pd.bdate_range('1/1/2009', periods=5), 43 | } 44 | return pd.DataFrame(data) 45 | 46 | 47 | def getSeriesData(): 48 | index = makeStringIndex(_N) 49 | return { 50 | c: pd.Series(np.random.default_rng(i).standard_normal(_N), index=index) 51 | for i, c in enumerate(getCols(_K)) 52 | } 53 | 54 | 55 | def makeDataFrame(): 56 | data = getSeriesData() 57 | return pd.DataFrame(data) 58 | 59 | 60 | def makeDateIndex(k=10, freq='B', name=None, **kwargs): 61 | dt = datetime(2000, 1, 1) 62 | dr = pd.bdate_range(dt, periods=k, freq=freq, name=name) 63 | return pd.DatetimeIndex(dr, name=name, **kwargs) 64 | 65 | 66 | def makeTimeSeries(nper=None, freq='B', name=None): 67 | if nper is None: 68 | nper = _N 69 | return pd.Series( 70 | np.random.default_rng(2).standard_normal(nper), 71 | index=makeDateIndex(nper, freq=freq), 72 | name=name, 73 | ) 74 | 75 | 76 | def getTimeSeriesData(nper=None, freq='B'): 77 | return {c: makeTimeSeries(nper, freq) for c in getCols(_K)} 78 | 79 | 80 | def makeTimeDataFrame(nper=None, freq='B'): 81 | data = getTimeSeriesData(nper, freq) 82 | return pd.DataFrame(data) 83 | -------------------------------------------------------------------------------- /hvplot/xarray.py: -------------------------------------------------------------------------------- 1 | import xarray as xr 2 | 3 | from panel.widgets import Widget 4 | 5 | from .interactive import Interactive 6 | 7 | 8 | class XArrayInteractive(Interactive): 9 | @classmethod 10 | def applies(cls, obj): 11 | return isinstance(obj, (xr.DataArray, xr.Dataset)) 12 | 13 | def sel(self, **kwargs): 14 | processed = {} 15 | for k, v in kwargs.items(): 16 | if isinstance(v, type) and issubclass(v, Widget): 17 | if hasattr(v, 'end'): 18 | values = self._current[k].values 19 | v = v(name=k, start=values.min(), end=values.max()) 20 | if hasattr(v, 'options'): 21 | v = v(name=k, options={str(v): v for v in self._current[k].values}) 22 | processed[k] = v 23 | self._method = 'sel' 24 | return self.__call__(**processed) 25 | 26 | sel.__doc__ = xr.DataArray.sel.__doc__ 27 | 28 | def isel(self, **kwargs): 29 | processed = {} 30 | for k, v in kwargs.items(): 31 | if isinstance(v, type) and issubclass(v, Widget): 32 | if hasattr(v, 'end'): 33 | v = v(name=k, end=len(self._current[k])) 34 | processed[k] = v 35 | self._method = 'isel' 36 | return self.__call__(**processed) 37 | 38 | isel.__doc__ = xr.DataArray.isel.__doc__ 39 | 40 | 41 | def patch(name='hvplot', interactive='interactive', extension='bokeh', logo=False): 42 | from . import hvPlot, post_patch, _module_extensions 43 | 44 | try: 45 | import xarray as xr 46 | except ImportError: 47 | raise ImportError( 48 | 'Could not patch plotting API onto xarray. xarray could not be imported.' 49 | ) 50 | 51 | # Remove the class docstring as it very developer focused 52 | XArrayInteractive.__doc__ = '' 53 | 54 | if 'hvplot.xarray' not in _module_extensions: 55 | xr.register_dataset_accessor(name)(hvPlot) 56 | xr.register_dataarray_accessor(name)(hvPlot) 57 | xr.register_dataset_accessor(interactive)(XArrayInteractive) 58 | xr.register_dataarray_accessor(interactive)(XArrayInteractive) 59 | _module_extensions.add('hvplot.xarray') 60 | 61 | post_patch(extension, logo) 62 | 63 | 64 | patch() 65 | -------------------------------------------------------------------------------- /scripts/conda/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euxo pipefail 4 | 5 | PACKAGE="hvplot" 6 | 7 | python -m build --sdist . 8 | 9 | VERSION=$(python -c "import $PACKAGE; print($PACKAGE._version.__version__)") 10 | export VERSION 11 | 12 | conda build scripts/conda/recipe --no-anaconda-upload --no-verify -c conda-forge --package-format 1 13 | 14 | mv "$CONDA_PREFIX/conda-bld/noarch/$PACKAGE-$VERSION-py_0.tar.bz2" dist 15 | -------------------------------------------------------------------------------- /scripts/conda/recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set pyproject = load_file_data('../../../pyproject.toml', from_recipe_dir=True) %} 2 | {% set buildsystem = pyproject['build-system'] %} 3 | {% set project = pyproject['project'] %} 4 | 5 | {% set name = project['name'] %} 6 | {% set version = VERSION %} 7 | 8 | package: 9 | name: {{ name|lower }} 10 | version: {{ version }} 11 | 12 | source: 13 | url: ../../../dist/{{ name }}-{{ version }}.tar.gz 14 | 15 | build: 16 | noarch: python 17 | script: {{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation 18 | 19 | requirements: 20 | build: 21 | - python {{ project['requires-python'] }} 22 | - pip 23 | {% for dep in buildsystem['requires'] %} 24 | - {{ dep }} 25 | {% endfor %} 26 | run: 27 | - python {{ project['requires-python'] }} 28 | {% for dep in project['dependencies'] %} 29 | - {{ dep }} 30 | {% endfor %} 31 | 32 | test: 33 | requires: 34 | - pip 35 | {% for dep in project['optional-dependencies']['tests-core'] %} 36 | {% if 'dask[dataframe]' in dep %} 37 | - {{ dep | replace("[dataframe]", "") }} 38 | {% elif 'bokeh_sampledata' in dep %} 39 | - {{ dep | replace("; python_version >= '3.10'", "") }} 40 | {% else %} 41 | - {{ dep }} 42 | {% endif %} 43 | {% endfor %} 44 | source_files: 45 | - pyproject.toml 46 | imports: 47 | - hvplot 48 | - hvplot.pandas 49 | commands: 50 | - python -c "import hvplot; ver = hvplot.__version__; assert ver != '0.0.0' and ver != 'unknown'" 51 | - pip check 52 | - pytest hvplot 53 | 54 | about: 55 | home: {{ project['urls']['Homepage'] }} 56 | summary: {{ project['description'] }} 57 | license: {{ project['license']['text'] }} 58 | license_file: LICENSE 59 | -------------------------------------------------------------------------------- /scripts/download_data.py: -------------------------------------------------------------------------------- 1 | import bokeh 2 | from packaging.version import Version 3 | 4 | if Version(bokeh.__version__).release < (3, 5, 0): 5 | import bokeh.sampledata 6 | 7 | bokeh.sampledata.download() 8 | print('bokeh data downloaded.') 9 | 10 | try: 11 | import pooch # noqa: F401 12 | import scipy # noqa: F401 13 | import xarray as xr 14 | 15 | xr.tutorial.open_dataset('air_temperature') 16 | xr.tutorial.open_dataset('rasm') 17 | print('xarray data downloaded.') 18 | except ModuleNotFoundError as e: 19 | print(f'ModuleNotFoundError when attempting to download xarray datasets : {e}') 20 | -------------------------------------------------------------------------------- /scripts/sync_git_tags.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to sync tags from upstream repository to forked repository 3 | """ 4 | 5 | import sys 6 | from subprocess import run 7 | 8 | 9 | def main(package: str) -> None: 10 | origin = run(['git', 'remote', 'get-url', 'origin'], check=True, capture_output=True) 11 | upstream = run(['git', 'remote', 'get-url', 'upstream'], check=False, capture_output=True) 12 | url = ( 13 | f'https://github.com/holoviz/{package}.git' 14 | if origin.stdout.startswith(b'http') 15 | else f'git@github.com:holoviz/{package}.git' 16 | ) 17 | 18 | if url == origin.stdout.strip().decode(): 19 | print('Not a forked repository, exiting.') 20 | return 21 | elif upstream.returncode: 22 | print(f'Adding {url!r} as remote upstream') 23 | run(['git', 'remote', 'add', 'upstream', url], check=True, capture_output=True) 24 | 25 | print(f'Syncing tags from {package} repository with your forked repository') 26 | run(['git', 'fetch', '--tags', 'upstream'], check=True, capture_output=True) 27 | run(['git', 'push', '--tags'], check=True, capture_output=True) 28 | 29 | 30 | if __name__ == '__main__': 31 | main(sys.argv[1]) 32 | --------------------------------------------------------------------------------