├── .github
├── CONTRIBUTING.md
├── dependabot.yml
└── workflows
│ └── ci.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── CITATION.cff
├── LICENSE.md
├── Makefile
├── README.md
├── SECURITY.md
├── ci
├── cache_datasets.py
├── check_gallery.py
├── deps_pinned.txt
└── getmsfonts.sh
├── doc
├── .gitignore
├── Makefile
├── README.md
├── _docstrings
│ ├── FacetGrid.ipynb
│ ├── JointGrid.ipynb
│ ├── Makefile
│ ├── PairGrid.ipynb
│ ├── axes_style.ipynb
│ ├── barplot.ipynb
│ ├── blend_palette.ipynb
│ ├── boxenplot.ipynb
│ ├── boxplot.ipynb
│ ├── catplot.ipynb
│ ├── clustermap.ipynb
│ ├── color_palette.ipynb
│ ├── countplot.ipynb
│ ├── cubehelix_palette.ipynb
│ ├── dark_palette.ipynb
│ ├── displot.ipynb
│ ├── diverging_palette.ipynb
│ ├── ecdfplot.ipynb
│ ├── heatmap.ipynb
│ ├── histplot.ipynb
│ ├── hls_palette.ipynb
│ ├── husl_palette.ipynb
│ ├── jointplot.ipynb
│ ├── kdeplot.ipynb
│ ├── light_palette.ipynb
│ ├── lineplot.ipynb
│ ├── lmplot.ipynb
│ ├── move_legend.ipynb
│ ├── mpl_palette.ipynb
│ ├── objects.Agg.ipynb
│ ├── objects.Area.ipynb
│ ├── objects.Band.ipynb
│ ├── objects.Bar.ipynb
│ ├── objects.Bars.ipynb
│ ├── objects.Count.ipynb
│ ├── objects.Dash.ipynb
│ ├── objects.Dodge.ipynb
│ ├── objects.Dot.ipynb
│ ├── objects.Dots.ipynb
│ ├── objects.Est.ipynb
│ ├── objects.Hist.ipynb
│ ├── objects.Jitter.ipynb
│ ├── objects.KDE.ipynb
│ ├── objects.Line.ipynb
│ ├── objects.Lines.ipynb
│ ├── objects.Norm.ipynb
│ ├── objects.Path.ipynb
│ ├── objects.Paths.ipynb
│ ├── objects.Perc.ipynb
│ ├── objects.Plot.add.ipynb
│ ├── objects.Plot.config.ipynb
│ ├── objects.Plot.facet.ipynb
│ ├── objects.Plot.label.ipynb
│ ├── objects.Plot.layout.ipynb
│ ├── objects.Plot.limit.ipynb
│ ├── objects.Plot.on.ipynb
│ ├── objects.Plot.pair.ipynb
│ ├── objects.Plot.scale.ipynb
│ ├── objects.Plot.share.ipynb
│ ├── objects.Plot.theme.ipynb
│ ├── objects.Range.ipynb
│ ├── objects.Shift.ipynb
│ ├── objects.Stack.ipynb
│ ├── objects.Text.ipynb
│ ├── pairplot.ipynb
│ ├── plotting_context.ipynb
│ ├── pointplot.ipynb
│ ├── regplot.ipynb
│ ├── relplot.ipynb
│ ├── residplot.ipynb
│ ├── rugplot.ipynb
│ ├── scatterplot.ipynb
│ ├── set_context.ipynb
│ ├── set_style.ipynb
│ ├── set_theme.ipynb
│ ├── stripplot.ipynb
│ ├── swarmplot.ipynb
│ └── violinplot.ipynb
├── _static
│ ├── copybutton.js
│ ├── css
│ │ └── custom.css
│ ├── favicon.ico
│ ├── favicon_old.ico
│ ├── logo-mark-darkbg.png
│ ├── logo-mark-darkbg.svg
│ ├── logo-mark-lightbg.png
│ ├── logo-mark-lightbg.svg
│ ├── logo-mark-whitebg.png
│ ├── logo-tall-darkbg.png
│ ├── logo-tall-darkbg.svg
│ ├── logo-tall-lightbg.png
│ ├── logo-tall-lightbg.svg
│ ├── logo-tall-whitebg.png
│ ├── logo-wide-darkbg.png
│ ├── logo-wide-darkbg.svg
│ ├── logo-wide-lightbg.png
│ ├── logo-wide-lightbg.svg
│ └── logo-wide-whitebg.png
├── _templates
│ ├── autosummary
│ │ ├── base.rst
│ │ ├── class.rst
│ │ ├── object.rst
│ │ ├── plot.rst
│ │ └── scale.rst
│ ├── layout.html
│ └── version.html
├── _tutorial
│ ├── Makefile
│ ├── aesthetics.ipynb
│ ├── axis_grids.ipynb
│ ├── categorical.ipynb
│ ├── color_palettes.ipynb
│ ├── data_structure.ipynb
│ ├── distributions.ipynb
│ ├── error_bars.ipynb
│ ├── function_overview.ipynb
│ ├── introduction.ipynb
│ ├── objects_interface.ipynb
│ ├── properties.ipynb
│ ├── regression.ipynb
│ └── relational.ipynb
├── api.rst
├── citing.rst
├── conf.py
├── example_thumbs
│ └── .gitkeep
├── faq.rst
├── index.rst
├── installing.rst
├── make.bat
├── matplotlibrc
├── sphinxext
│ ├── gallery_generator.py
│ └── tutorial_builder.py
├── tools
│ ├── extract_examples.py
│ ├── generate_logos.py
│ ├── nb_to_doc.py
│ └── set_nb_kernels.py
├── tutorial.yaml
└── whatsnew
│ ├── index.rst
│ ├── v0.10.0.rst
│ ├── v0.10.1.rst
│ ├── v0.11.0.rst
│ ├── v0.11.1.rst
│ ├── v0.11.2.rst
│ ├── v0.12.0.rst
│ ├── v0.12.1.rst
│ ├── v0.12.2.rst
│ ├── v0.13.0.rst
│ ├── v0.13.1.rst
│ ├── v0.13.2.rst
│ ├── v0.2.0.rst
│ ├── v0.2.1.rst
│ ├── v0.3.0.rst
│ ├── v0.3.1.rst
│ ├── v0.4.0.rst
│ ├── v0.5.0.rst
│ ├── v0.5.1.rst
│ ├── v0.6.0.rst
│ ├── v0.7.0.rst
│ ├── v0.7.1.rst
│ ├── v0.8.0.rst
│ ├── v0.8.1.rst
│ ├── v0.9.0.rst
│ └── v0.9.1.rst
├── examples
├── .gitignore
├── anscombes_quartet.py
├── different_scatter_variables.py
├── errorband_lineplots.py
├── faceted_histogram.py
├── faceted_lineplot.py
├── grouped_barplot.py
├── grouped_boxplot.py
├── grouped_violinplots.py
├── heat_scatter.py
├── hexbin_marginals.py
├── histogram_stacked.py
├── horizontal_boxplot.py
├── jitter_stripplot.py
├── joint_histogram.py
├── joint_kde.py
├── kde_ridgeplot.py
├── large_distributions.py
├── layered_bivariate_plot.py
├── logistic_regression.py
├── many_facets.py
├── many_pairwise_correlations.py
├── marginal_ticks.py
├── multiple_bivariate_kde.py
├── multiple_conditional_kde.py
├── multiple_ecdf.py
├── multiple_regression.py
├── pair_grid_with_kde.py
├── paired_pointplots.py
├── pairgrid_dotplot.py
├── palette_choices.py
├── palette_generation.py
├── part_whole_bars.py
├── pointplot_anova.py
├── radial_facets.py
├── regression_marginals.py
├── residplot.py
├── scatter_bubbles.py
├── scatterplot_categorical.py
├── scatterplot_matrix.py
├── scatterplot_sizes.py
├── simple_violinplots.py
├── smooth_bivariate_kde.py
├── spreadsheet_heatmap.py
├── strip_regplot.py
├── structured_heatmap.py
├── three_variable_histogram.py
├── timeseries_facets.py
├── wide_data_lineplot.py
└── wide_form_violinplot.py
├── licences
├── APPDIRS_LICENSE
├── HUSL_LICENSE
├── NUMPYDOC_LICENSE
├── PACKAGING_LICENSE
└── SCIPY_LICENSE
├── pyproject.toml
├── seaborn
├── __init__.py
├── _base.py
├── _compat.py
├── _core
│ ├── __init__.py
│ ├── data.py
│ ├── exceptions.py
│ ├── groupby.py
│ ├── moves.py
│ ├── plot.py
│ ├── properties.py
│ ├── rules.py
│ ├── scales.py
│ ├── subplots.py
│ └── typing.py
├── _docstrings.py
├── _marks
│ ├── __init__.py
│ ├── area.py
│ ├── bar.py
│ ├── base.py
│ ├── dot.py
│ ├── line.py
│ └── text.py
├── _statistics.py
├── _stats
│ ├── __init__.py
│ ├── aggregation.py
│ ├── base.py
│ ├── counting.py
│ ├── density.py
│ ├── order.py
│ └── regression.py
├── _testing.py
├── algorithms.py
├── axisgrid.py
├── categorical.py
├── cm.py
├── colors
│ ├── __init__.py
│ ├── crayons.py
│ └── xkcd_rgb.py
├── distributions.py
├── external
│ ├── __init__.py
│ ├── appdirs.py
│ ├── docscrape.py
│ ├── husl.py
│ ├── kde.py
│ └── version.py
├── matrix.py
├── miscplot.py
├── objects.py
├── palettes.py
├── rcmod.py
├── regression.py
├── relational.py
├── utils.py
└── widgets.py
├── setup.cfg
└── tests
├── __init__.py
├── _core
├── __init__.py
├── test_data.py
├── test_groupby.py
├── test_moves.py
├── test_plot.py
├── test_properties.py
├── test_rules.py
├── test_scales.py
└── test_subplots.py
├── _marks
├── __init__.py
├── test_area.py
├── test_bar.py
├── test_base.py
├── test_dot.py
├── test_line.py
└── test_text.py
├── _stats
├── __init__.py
├── test_aggregation.py
├── test_counting.py
├── test_density.py
├── test_order.py
└── test_regression.py
├── conftest.py
├── test_algorithms.py
├── test_axisgrid.py
├── test_base.py
├── test_categorical.py
├── test_distributions.py
├── test_docstrings.py
├── test_matrix.py
├── test_miscplot.py
├── test_objects.py
├── test_palettes.py
├── test_rcmod.py
├── test_regression.py
├── test_relational.py
├── test_statistics.py
└── test_utils.py
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing to seaborn
2 | =======================
3 |
4 | General support
5 | ---------------
6 |
7 | General support questions ("how do I do X?") are most at home on [StackOverflow](https://stackoverflow.com/), which has a larger audience of people who will see your post and may be able to offer assistance. Your chance of getting a quick answer will be higher if you include runnable code, a precise statement of what you are hoping to achieve, and a clear explanation of the problems that you have encountered.
8 |
9 | Reporting bugs
10 | --------------
11 |
12 | If you think you've encountered a bug in seaborn, please report it on the [Github issue tracker](https://github.com/mwaskom/seaborn/issues/new). To be useful, bug reports *must* include the following information:
13 |
14 | - A reproducible code example that demonstrates the problem
15 | - The output that you are seeing (an image of a plot, or the error message)
16 | - A clear explanation of why you think something is wrong
17 | - The specific versions of seaborn and matplotlib that you are working with
18 |
19 | Bug reports are easiest to address if they can be demonstrated using one of the example datasets from the seaborn docs (i.e. with `seaborn.load_dataset`). Otherwise, it is preferable that your example generate synthetic data to reproduce the problem. If you can only demonstrate the issue with your actual dataset, you will need to share it, ideally as a csv (do not share data as a pickle file).
20 |
21 | If you've encountered an error, searching the specific text of the message before opening a new issue can often help you solve the problem quickly and avoid making a duplicate report.
22 |
23 | Because matplotlib handles the actual rendering, errors or incorrect outputs may be due to a problem in matplotlib rather than one in seaborn. It can save time if you try to reproduce the issue in an example that uses only matplotlib, so that you can report it in the right place. But it is alright to skip this step if it's not obvious how to do it.
24 |
25 |
26 | New features
27 | ------------
28 |
29 | If you think there is a new feature that should be added to seaborn, you can open an issue to discuss it. But please be aware that current development efforts are mostly focused on standardizing the API and internals, and there may be relatively low enthusiasm for novel features that do not fit well into short- and medium-term development plans.
30 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | # Check for updates to GitHub Actions every week
8 | interval: "weekly"
9 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [master, v0.*]
6 | pull_request:
7 | branches: master
8 | schedule:
9 | - cron: '0 6 * * 1,4' # Each Monday and Thursday at 06:00 UTC
10 | workflow_dispatch:
11 |
12 | permissions:
13 | contents: read
14 |
15 | env:
16 | NB_KERNEL: python
17 | MPLBACKEND: Agg
18 | SEABORN_DATA: ${{ github.workspace }}/seaborn-data
19 | PYDEVD_DISABLE_FILE_VALIDATION: 1
20 |
21 | jobs:
22 | build-docs:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
26 |
27 | - name: Setup Python 3.11
28 | uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
29 | with:
30 | python-version: "3.11"
31 |
32 | - name: Install seaborn
33 | run: |
34 | pip install --upgrade pip
35 | pip install .[stats,docs]
36 |
37 | - name: Install pandoc
38 | run: |
39 | wget https://github.com/jgm/pandoc/releases/download/3.1.11/pandoc-3.1.11-1-amd64.deb
40 | sudo dpkg -i pandoc-3.1.11-1-amd64.deb
41 |
42 | - name: Cache datasets
43 | run: |
44 | git clone https://github.com/mwaskom/seaborn-data.git
45 | ls $SEABORN_DATA
46 |
47 | - name: Build docs
48 | env:
49 | SPHINXOPTS: -j `nproc`
50 | run: |
51 | cd doc
52 | make -j `nproc` notebooks
53 | make html
54 |
55 |
56 | run-tests:
57 | runs-on: ubuntu-latest
58 |
59 | strategy:
60 | matrix:
61 | python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
62 | install: [full]
63 | deps: [latest]
64 |
65 | include:
66 | - python: "3.8"
67 | install: full
68 | deps: pinned
69 | - python: "3.11"
70 | install: light
71 | deps: latest
72 |
73 | steps:
74 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
75 |
76 | - name: Setup Python ${{ matrix.python }}
77 | uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
78 | with:
79 | python-version: ${{ matrix.python }}
80 | allow-prereleases: true
81 |
82 | - name: Install seaborn
83 | run: |
84 | pip install --upgrade pip wheel
85 | if [[ ${{matrix.install}} == 'full' ]]; then EXTRAS=',stats'; fi
86 | if [[ ${{matrix.deps }} == 'pinned' ]]; then DEPS='-r ci/deps_pinned.txt'; fi
87 | pip install .[dev$EXTRAS] $DEPS
88 |
89 | - name: Run tests
90 | run: make test
91 |
92 | - name: Upload coverage
93 | uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
94 | if: ${{ success() }}
95 |
96 | lint:
97 | runs-on: ubuntu-latest
98 | strategy:
99 | fail-fast: false
100 | steps:
101 |
102 | - name: Checkout
103 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
104 |
105 | - name: Setup Python
106 | uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
107 |
108 | - name: Install tools
109 | run: pip install mypy~=1.10.0 flake8
110 |
111 | - name: Flake8
112 | run: make lint
113 |
114 | - name: Type checking
115 | run: make typecheck
116 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.sw*
3 | build/
4 | .ipynb_checkpoints/
5 | dist/
6 | seaborn.egg-info/
7 | .cache/
8 | .coverage
9 | cover/
10 | htmlcov/
11 | .idea/
12 | .vscode/
13 | .pytest_cache/
14 | .DS_Store
15 | notes/
16 | notebooks/
17 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.3.0
4 | hooks:
5 | - id: check-yaml
6 | - id: end-of-file-fixer
7 | - id: trailing-whitespace
8 | exclude: \.svg$
9 | - repo: https://github.com/pycqa/flake8
10 | rev: 5.0.4
11 | hooks:
12 | - id: flake8
13 | exclude: seaborn/(cm\.py|external/)
14 | types: [file, python]
15 | - repo: https://github.com/pre-commit/mirrors-mypy
16 | rev: v0.971
17 | hooks:
18 | - id: mypy
19 | args: [--follow-imports=skip]
20 | files: seaborn/_(core|marks|stats)/
21 |
--------------------------------------------------------------------------------
/CITATION.cff:
--------------------------------------------------------------------------------
1 | cff-version: 1.2.0
2 | message: "If seaborn is integral to a scientific publication, please cite the following paper:"
3 | preferred-citation:
4 | type: article
5 | authors:
6 | - family-names: "Waskom"
7 | given-names: "Michael Lawrence"
8 | orcid: "https://orcid.org/0000-0002-9817-6869"
9 | doi: "10.21105/joss.03021"
10 | journal: "Journal of Open Source Software"
11 | month: April
12 | title: "seaborn: statistical data visualization"
13 | issue: 6
14 | volume: 60
15 | year: 2021
16 | url: "https://joss.theoj.org/papers/10.21105/joss.03021"
17 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2023, Michael L. Waskom
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of the project nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | export SHELL := /bin/bash
2 |
3 | test:
4 | pytest -n auto --cov=seaborn --cov=tests --cov-config=setup.cfg tests
5 |
6 | lint:
7 | flake8 seaborn/ tests/
8 |
9 | typecheck:
10 | mypy --follow-imports=skip seaborn/_core seaborn/_marks seaborn/_stats
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | --------------------------------------
4 |
5 | seaborn: statistical data visualization
6 | =======================================
7 |
8 | [](https://pypi.org/project/seaborn/)
9 | [](https://github.com/mwaskom/seaborn/blob/master/LICENSE.md)
10 | [](https://doi.org/10.21105/joss.03021)
11 | [](https://github.com/mwaskom/seaborn/actions)
12 | [](https://codecov.io/gh/mwaskom/seaborn)
13 |
14 | Seaborn is a Python visualization library based on matplotlib. It provides a high-level interface for drawing attractive statistical graphics.
15 |
16 |
17 | Documentation
18 | -------------
19 |
20 | Online documentation is available at [seaborn.pydata.org](https://seaborn.pydata.org).
21 |
22 | The docs include a [tutorial](https://seaborn.pydata.org/tutorial.html), [example gallery](https://seaborn.pydata.org/examples/index.html), [API reference](https://seaborn.pydata.org/api.html), [FAQ](https://seaborn.pydata.org/faq), and other useful information.
23 |
24 | To build the documentation locally, please refer to [`doc/README.md`](doc/README.md).
25 |
26 | Dependencies
27 | ------------
28 |
29 | Seaborn supports Python 3.8+.
30 |
31 | Installation requires [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), and [matplotlib](https://matplotlib.org/). Some advanced statistical functionality requires [scipy](https://www.scipy.org/) and/or [statsmodels](https://www.statsmodels.org/).
32 |
33 |
34 | Installation
35 | ------------
36 |
37 | The latest stable release (and required dependencies) can be installed from PyPI:
38 |
39 | pip install seaborn
40 |
41 | It is also possible to include optional statistical dependencies:
42 |
43 | pip install seaborn[stats]
44 |
45 | Seaborn can also be installed with conda:
46 |
47 | conda install seaborn
48 |
49 | Note that the main anaconda repository lags PyPI in adding new releases, but conda-forge (`-c conda-forge`) typically updates quickly.
50 |
51 | Citing
52 | ------
53 |
54 | A paper describing seaborn has been published in the [Journal of Open Source Software](https://joss.theoj.org/papers/10.21105/joss.03021). The paper provides an introduction to the key features of the library, and it can be used as a citation if seaborn proves integral to a scientific publication.
55 |
56 | Testing
57 | -------
58 |
59 | Testing seaborn requires installing additional dependencies; they can be installed with the `dev` extra (e.g., `pip install .[dev]`).
60 |
61 | To test the code, run `make test` in the source directory. This will exercise the unit tests (using [pytest](https://docs.pytest.org/)) and generate a coverage report.
62 |
63 | Code style is enforced with `flake8` using the settings in the [`setup.cfg`](./setup.cfg) file. Run `make lint` to check. Alternately, you can use `pre-commit` to automatically run lint checks on any files you are committing: just run `pre-commit install` to set it up, and then commit as usual going forward.
64 |
65 | Development
66 | -----------
67 |
68 | Seaborn development takes place on Github: https://github.com/mwaskom/seaborn
69 |
70 | Please submit bugs that you encounter to the [issue tracker](https://github.com/mwaskom/seaborn/issues) with a reproducible example demonstrating the problem. Questions about usage are more at home on StackOverflow, where there is a [seaborn tag](https://stackoverflow.com/questions/tagged/seaborn).
71 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | If you have discovered a security vulnerability in this project, please report it
4 | privately. **Do not disclose it as a public issue.** This gives me time to work with you
5 | to fix the issue before public exposure, reducing the chance that the exploit will be
6 | used before a patch is released.
7 |
8 | You may submit the report by filling out
9 | [this form](https://github.com/mwaskom/seaborn/security/advisories/new).
10 |
11 | Please provide the following information in your report:
12 |
13 | - A description of the vulnerability and its impact
14 | - How to reproduce the issue
15 |
16 | This project is maintained by a single maintainer on a reasonable-effort basis. As such,
17 | I ask that you give me 90 days to work on a fix before public exposure.
18 |
--------------------------------------------------------------------------------
/ci/cache_datasets.py:
--------------------------------------------------------------------------------
1 | """
2 | Cache test datasets before running tests / building docs.
3 |
4 | Avoids race conditions that would arise from parallelization.
5 | """
6 | import pathlib
7 | import re
8 |
9 | from seaborn import load_dataset
10 |
11 | path = pathlib.Path(".")
12 | py_files = path.rglob("*.py")
13 | ipynb_files = path.rglob("*.ipynb")
14 |
15 | datasets = []
16 |
17 | for fname in py_files:
18 | with open(fname) as fid:
19 | datasets += re.findall(r"load_dataset\(['\"](\w+)['\"]", fid.read())
20 |
21 | for p in ipynb_files:
22 | with p.open() as fid:
23 | datasets += re.findall(r"load_dataset\(\\['\"](\w+)\\['\"]", fid.read())
24 |
25 | for name in sorted(set(datasets)):
26 | print(f"Caching {name}")
27 | load_dataset(name)
28 |
--------------------------------------------------------------------------------
/ci/check_gallery.py:
--------------------------------------------------------------------------------
1 | """Execute the scripts that comprise the example gallery in the online docs."""
2 | from glob import glob
3 | import matplotlib.pyplot as plt
4 |
5 | if __name__ == "__main__":
6 |
7 | fnames = sorted(glob("examples/*.py"))
8 |
9 | for fname in fnames:
10 |
11 | print(f"- {fname}")
12 | with open(fname) as fid:
13 | exec(fid.read())
14 | plt.close("all")
15 |
--------------------------------------------------------------------------------
/ci/deps_pinned.txt:
--------------------------------------------------------------------------------
1 | numpy~=1.20.0
2 | pandas~=1.2.0
3 | matplotlib~=3.4.0
4 | scipy~=1.7.0
5 | statsmodels~=0.12.0
6 | pillow~=10.3.0
7 |
--------------------------------------------------------------------------------
/ci/getmsfonts.sh:
--------------------------------------------------------------------------------
1 | echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
2 | apt-get install msttcorefonts -qq
3 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | *_files/
2 | _build/
3 | generated/
4 | examples/
5 | example_thumbs/*.png
6 | docstrings/
7 | tutorial/
8 | tutorial/_images
9 | tutorial.rst
10 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | Building the seaborn docs
2 | =========================
3 |
4 | Building the docs requires additional dependencies; they can be installed with `pip install seaborn[stats,docs]`.
5 |
6 | The build process involves conversion of Jupyter notebooks to `rst` files. To facilitate this, you may need to set `NB_KERNEL` environment variable to the name of a kernel on your machine (e.g. `export NB_KERNEL="python3"`). To get a list of available Python kernels, run `jupyter kernelspec list`.
7 |
8 | After you're set up, run `make notebooks html` from the `doc` directory to convert all notebooks, generate all gallery examples, and build the documentation itself. The site will live in `_build/html`.
9 |
10 | Run `make clean` to delete the built site and all intermediate files. Run `make -C docstrings clean` or `make -C tutorial clean` to remove intermediate files for the API or tutorial components.
11 |
12 | If your goal is to obtain an offline copy of the docs for a released version, it may be easier to clone the [website repository](https://github.com/seaborn/seaborn.github.io) or to download a zipfile corresponding to a [specific version](https://github.com/seaborn/seaborn.github.io/tags).
13 |
--------------------------------------------------------------------------------
/doc/_docstrings/Makefile:
--------------------------------------------------------------------------------
1 | rst_files := $(patsubst %.ipynb,../docstrings/%.rst,$(wildcard *.ipynb))
2 | export MPLBACKEND := module://matplotlib_inline.backend_inline
3 |
4 | docstrings: ${rst_files}
5 |
6 | ../docstrings/%.rst: %.ipynb
7 | ../tools/nb_to_doc.py $*.ipynb ../docstrings
8 | @cp -r ../docstrings/$*_files ../generated/
9 | @if [ -f ../generated/seaborn.$*.rst ]; then \
10 | touch ../generated/seaborn.$*.rst; \
11 | fi
12 |
13 | clean:
14 | rm -rf ../docstrings
15 |
--------------------------------------------------------------------------------
/doc/_docstrings/axes_style.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "dated-mother",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "id": "prospective-sellers",
20 | "metadata": {},
21 | "source": [
22 | "Calling with no arguments will return the current defaults for the style parameters:"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "recognized-rehabilitation",
29 | "metadata": {
30 | "tags": [
31 | "show-output"
32 | ]
33 | },
34 | "outputs": [],
35 | "source": [
36 | "sns.axes_style()"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "id": "furnished-irrigation",
42 | "metadata": {},
43 | "source": [
44 | "Calling with the name of a predefined style will show those parameter values:"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": null,
50 | "id": "coordinate-reward",
51 | "metadata": {
52 | "tags": [
53 | "show-output"
54 | ]
55 | },
56 | "outputs": [],
57 | "source": [
58 | "sns.axes_style(\"darkgrid\")"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "id": "mediterranean-picking",
64 | "metadata": {},
65 | "source": [
66 | "Use the function as a context manager to temporarily change the style of your plots:"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": null,
72 | "id": "missing-essence",
73 | "metadata": {},
74 | "outputs": [],
75 | "source": [
76 | "with sns.axes_style(\"whitegrid\"):\n",
77 | " sns.barplot(x=[1, 2, 3], y=[2, 5, 3])"
78 | ]
79 | }
80 | ],
81 | "metadata": {
82 | "kernelspec": {
83 | "display_name": "py310",
84 | "language": "python",
85 | "name": "py310"
86 | },
87 | "language_info": {
88 | "codemirror_mode": {
89 | "name": "ipython",
90 | "version": 3
91 | },
92 | "file_extension": ".py",
93 | "mimetype": "text/x-python",
94 | "name": "python",
95 | "nbconvert_exporter": "python",
96 | "pygments_lexer": "ipython3",
97 | "version": "3.10.6"
98 | }
99 | },
100 | "nbformat": 4,
101 | "nbformat_minor": 5
102 | }
103 |
--------------------------------------------------------------------------------
/doc/_docstrings/blend_palette.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "8f97280e-cec8-42b2-a968-4fd4364594f8",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "sns.palettes._patch_colormap_display()"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "972edede-df1a-4010-9674-00b864d020e2",
22 | "metadata": {},
23 | "source": [
24 | "Pass a list of two colors to interpolate between them:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "e6ae2547-1042-4ac0-84ea-6f37a0229871",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.blend_palette([\"b\", \"r\"])"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "1d983eac-2dd5-4746-b27f-4dfa19b5e091",
40 | "metadata": {},
41 | "source": [
42 | "The color list can be arbitrarily long, and any color format can be used:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "846b78fd-30ce-4507-93f4-4274122c1987",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.blend_palette([\"#45a872\", \".8\", \"xkcd:golden\"])"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "318fef32-1f83-44d9-9ff9-21fa0231b7c6",
58 | "metadata": {},
59 | "source": [
60 | "Return a continuous colormap instead of a discrete palette:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "f0a05bc3-c60b-47a1-b276-d2e28a4a8226",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.blend_palette([\"#bdc\", \"#7b9\", \"#47a\"], as_cmap=True)"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": null,
76 | "id": "0473a402-0ec2-4877-81d2-ed6c57aefc77",
77 | "metadata": {},
78 | "outputs": [],
79 | "source": []
80 | }
81 | ],
82 | "metadata": {
83 | "kernelspec": {
84 | "display_name": "py310",
85 | "language": "python",
86 | "name": "py310"
87 | },
88 | "language_info": {
89 | "codemirror_mode": {
90 | "name": "ipython",
91 | "version": 3
92 | },
93 | "file_extension": ".py",
94 | "mimetype": "text/x-python",
95 | "name": "python",
96 | "nbconvert_exporter": "python",
97 | "pygments_lexer": "ipython3",
98 | "version": "3.10.6"
99 | }
100 | },
101 | "nbformat": 4,
102 | "nbformat_minor": 5
103 | }
104 |
--------------------------------------------------------------------------------
/doc/_docstrings/countplot.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2fdf0f63-d515-4cb8-b3e0-62cac7852b12",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme(style=\"whitegrid\")\n",
16 | "titanic = sns.load_dataset(\"titanic\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "af16d745-734a-4f11-9f8f-fa54deadfb12",
22 | "metadata": {},
23 | "source": [
24 | "Show the count of value for a single categorical variable:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "6e9d0485-870d-4841-9c84-6e0bacbde7db",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.countplot(titanic, x=\"class\")"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "173f47c4-d5fb-4fc0-bdbd-ec228419d451",
40 | "metadata": {},
41 | "source": [
42 | "Group by a second variable:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "26f73c00-a2b3-45c3-b3cd-2babe0a81894",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.countplot(titanic, x=\"class\", hue=\"survived\")"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "377bfb01-64a2-4f07-b06b-fb1a4f7c3b12",
58 | "metadata": {},
59 | "source": [
60 | "Normalize the counts to show percentages:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "7267aefc-f2bc-4a64-956a-bb25013ca9ec",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.countplot(titanic, x=\"class\", hue=\"survived\", stat=\"percent\")"
71 | ]
72 | }
73 | ],
74 | "metadata": {
75 | "kernelspec": {
76 | "display_name": "py310",
77 | "language": "python",
78 | "name": "py310"
79 | },
80 | "language_info": {
81 | "codemirror_mode": {
82 | "name": "ipython",
83 | "version": 3
84 | },
85 | "file_extension": ".py",
86 | "mimetype": "text/x-python",
87 | "name": "python",
88 | "nbconvert_exporter": "python",
89 | "pygments_lexer": "ipython3",
90 | "version": "3.10.6"
91 | }
92 | },
93 | "nbformat": 4,
94 | "nbformat_minor": 5
95 | }
96 |
--------------------------------------------------------------------------------
/doc/_docstrings/dark_palette.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "5cd1cbb8-ba1a-460b-8e3a-bc285867f1d1",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "sns.palettes._patch_colormap_display()"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "b157eb25-015f-4dd6-9785-83ba19cf4f94",
22 | "metadata": {},
23 | "source": [
24 | "Define a sequential ramp from a dark gray to a specified color:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "5b655d28-9855-4528-8b8e-a6c50288fd1b",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.dark_palette(\"seagreen\")"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "50053b26-112a-4378-8ef0-9be0fb565ec7",
40 | "metadata": {},
41 | "source": [
42 | "Specify the color with a hex code:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "74ae0d17-f65b-4bcf-ae66-d97d46964d5c",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.dark_palette(\"#79C\")"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "eea376a2-fdf5-40e4-a187-3a28af529072",
58 | "metadata": {},
59 | "source": [
60 | "Specify the color from the husl system:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "66e451ee-869a-41ea-8dc5-4240b11e7be5",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.dark_palette((20, 60, 50), input=\"husl\")"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "e4f44dcd-cf49-4920-ac05-b4db67870363",
76 | "metadata": {},
77 | "source": [
78 | "Increase the number of colors:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "75985f07-de92-4d8b-89d5-caf445b9375e",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "sns.dark_palette(\"xkcd:golden\", 8)"
89 | ]
90 | },
91 | {
92 | "cell_type": "raw",
93 | "id": "34687ae8-fd6d-427a-a639-208f19e61122",
94 | "metadata": {},
95 | "source": [
96 | "Return a continuous colormap rather than a discrete palette:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "2c342db4-7f97-40f5-934e-9a82201890d1",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "sns.dark_palette(\"#b285bc\", as_cmap=True)"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "id": "e7ebe64b-25fa-4c52-9ebe-fdcbba0ee51e",
113 | "metadata": {},
114 | "outputs": [],
115 | "source": []
116 | }
117 | ],
118 | "metadata": {
119 | "kernelspec": {
120 | "display_name": "py310",
121 | "language": "python",
122 | "name": "py310"
123 | },
124 | "language_info": {
125 | "codemirror_mode": {
126 | "name": "ipython",
127 | "version": 3
128 | },
129 | "file_extension": ".py",
130 | "mimetype": "text/x-python",
131 | "name": "python",
132 | "nbconvert_exporter": "python",
133 | "pygments_lexer": "ipython3",
134 | "version": "3.10.6"
135 | }
136 | },
137 | "nbformat": 4,
138 | "nbformat_minor": 5
139 | }
140 |
--------------------------------------------------------------------------------
/doc/_docstrings/ecdfplot.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "Plot a univariate distribution along the x axis:"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {
14 | "tags": [
15 | "hide"
16 | ]
17 | },
18 | "outputs": [],
19 | "source": [
20 | "import seaborn as sns; sns.set_theme()"
21 | ]
22 | },
23 | {
24 | "cell_type": "code",
25 | "execution_count": null,
26 | "metadata": {},
27 | "outputs": [],
28 | "source": [
29 | "penguins = sns.load_dataset(\"penguins\")\n",
30 | "sns.ecdfplot(data=penguins, x=\"flipper_length_mm\")"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "metadata": {},
36 | "source": [
37 | "Flip the plot by assigning the data variable to the y axis:"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": null,
43 | "metadata": {},
44 | "outputs": [],
45 | "source": [
46 | "sns.ecdfplot(data=penguins, y=\"flipper_length_mm\")"
47 | ]
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {},
52 | "source": [
53 | "If neither `x` nor `y` is assigned, the dataset is treated as wide-form, and a histogram is drawn for each numeric column:"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": null,
59 | "metadata": {},
60 | "outputs": [],
61 | "source": [
62 | "sns.ecdfplot(data=penguins.filter(like=\"bill_\", axis=\"columns\"))"
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "metadata": {},
68 | "source": [
69 | "You can also draw multiple histograms from a long-form dataset with hue mapping:"
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "execution_count": null,
75 | "metadata": {},
76 | "outputs": [],
77 | "source": [
78 | "sns.ecdfplot(data=penguins, x=\"bill_length_mm\", hue=\"species\")"
79 | ]
80 | },
81 | {
82 | "cell_type": "markdown",
83 | "metadata": {},
84 | "source": [
85 | "The default distribution statistic is normalized to show a proportion, but you can show absolute counts or percents instead:"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "execution_count": null,
91 | "metadata": {},
92 | "outputs": [],
93 | "source": [
94 | "sns.ecdfplot(data=penguins, x=\"bill_length_mm\", hue=\"species\", stat=\"count\")"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {},
100 | "source": [
101 | "It's also possible to plot the empirical complementary CDF (1 - CDF):"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "execution_count": null,
107 | "metadata": {},
108 | "outputs": [],
109 | "source": [
110 | "sns.ecdfplot(data=penguins, x=\"bill_length_mm\", hue=\"species\", complementary=True)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": []
119 | }
120 | ],
121 | "metadata": {
122 | "kernelspec": {
123 | "display_name": "py310",
124 | "language": "python",
125 | "name": "py310"
126 | },
127 | "language_info": {
128 | "codemirror_mode": {
129 | "name": "ipython",
130 | "version": 3
131 | },
132 | "file_extension": ".py",
133 | "mimetype": "text/x-python",
134 | "name": "python",
135 | "nbconvert_exporter": "python",
136 | "pygments_lexer": "ipython3",
137 | "version": "3.10.6"
138 | }
139 | },
140 | "nbformat": 4,
141 | "nbformat_minor": 4
142 | }
143 |
--------------------------------------------------------------------------------
/doc/_docstrings/husl_palette.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "a6794650-f28f-40eb-95a7-3f0e5c4b332d",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "sns.palettes._patch_colormap_display()"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "fab2f86e-45d4-4982-ade7-0a5ea6d762d1",
22 | "metadata": {},
23 | "source": [
24 | "By default, return 6 colors with identical lightness and saturation and evenly-sampled hues:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "b220950e-0ca2-4101-b56a-14eebe8ee8d0",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.husl_palette()"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "c5e4a2e3-e6b8-42bf-be19-348ff7ae2798",
40 | "metadata": {},
41 | "source": [
42 | "Increase the number of colors:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "7d0af740-cfca-49fb-a472-1daa4ccb3f3a",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.husl_palette(8)"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "1a7189f2-2a26-446a-90e7-cf41dcac4f25",
58 | "metadata": {},
59 | "source": [
60 | "Decrease the lightness:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "43af79c7-f497-41e5-874a-83eed99500f3",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.husl_palette(l=.4)"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "6d4099b7-5115-4365-b120-33a345581f5d",
76 | "metadata": {},
77 | "source": [
78 | "Decrease the saturation:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "52c1afc7-d982-4199-b218-222aa94563c5",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "sns.husl_palette(s=.4)"
89 | ]
90 | },
91 | {
92 | "cell_type": "raw",
93 | "id": "d26131ac-0d11-48c5-88b1-4e5cf9383000",
94 | "metadata": {},
95 | "source": [
96 | "Change the start-point for hue sampling:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "d72f06a0-13e0-47f7-bc70-4c5935eaa130",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "sns.husl_palette(h=.5)"
107 | ]
108 | },
109 | {
110 | "cell_type": "raw",
111 | "id": "7e6c3c19-41d3-4315-b03e-909d201d0e76",
112 | "metadata": {},
113 | "source": [
114 | "Return a continuous colormap:"
115 | ]
116 | },
117 | {
118 | "cell_type": "code",
119 | "execution_count": null,
120 | "id": "49c18838-0589-496f-9a61-635195c07f61",
121 | "metadata": {},
122 | "outputs": [],
123 | "source": [
124 | "sns.husl_palette(as_cmap=True)"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": null,
130 | "id": "c710a557-8e84-44cb-ab4c-baabcc4fd328",
131 | "metadata": {},
132 | "outputs": [],
133 | "source": []
134 | }
135 | ],
136 | "metadata": {
137 | "kernelspec": {
138 | "display_name": "py310",
139 | "language": "python",
140 | "name": "py310"
141 | },
142 | "language_info": {
143 | "codemirror_mode": {
144 | "name": "ipython",
145 | "version": 3
146 | },
147 | "file_extension": ".py",
148 | "mimetype": "text/x-python",
149 | "name": "python",
150 | "nbconvert_exporter": "python",
151 | "pygments_lexer": "ipython3",
152 | "version": "3.10.6"
153 | }
154 | },
155 | "nbformat": 4,
156 | "nbformat_minor": 5
157 | }
158 |
--------------------------------------------------------------------------------
/doc/_docstrings/light_palette.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "5cd1cbb8-ba1a-460b-8e3a-bc285867f1d1",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "sns.palettes._patch_colormap_display()"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "b157eb25-015f-4dd6-9785-83ba19cf4f94",
22 | "metadata": {},
23 | "source": [
24 | "Define a sequential ramp from a light gray to a specified color:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "851a4742-6276-4383-b17e-480beb896877",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.light_palette(\"seagreen\")"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "50053b26-112a-4378-8ef0-9be0fb565ec7",
40 | "metadata": {},
41 | "source": [
42 | "Specify the color with a hex code:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "74ae0d17-f65b-4bcf-ae66-d97d46964d5c",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.light_palette(\"#79C\")"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "eea376a2-fdf5-40e4-a187-3a28af529072",
58 | "metadata": {},
59 | "source": [
60 | "Specify the color from the husl system:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "66e451ee-869a-41ea-8dc5-4240b11e7be5",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.light_palette((20, 60, 50), input=\"husl\")"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "e4f44dcd-cf49-4920-ac05-b4db67870363",
76 | "metadata": {},
77 | "source": [
78 | "Increase the number of colors:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "75985f07-de92-4d8b-89d5-caf445b9375e",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "sns.light_palette(\"xkcd:copper\", 8)"
89 | ]
90 | },
91 | {
92 | "cell_type": "raw",
93 | "id": "34687ae8-fd6d-427a-a639-208f19e61122",
94 | "metadata": {},
95 | "source": [
96 | "Return a continuous colormap rather than a discrete palette:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "2c342db4-7f97-40f5-934e-9a82201890d1",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "sns.light_palette(\"#a275ac\", as_cmap=True)"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "id": "e7ebe64b-25fa-4c52-9ebe-fdcbba0ee51e",
113 | "metadata": {},
114 | "outputs": [],
115 | "source": []
116 | }
117 | ],
118 | "metadata": {
119 | "kernelspec": {
120 | "display_name": "py310",
121 | "language": "python",
122 | "name": "py310"
123 | },
124 | "language_info": {
125 | "codemirror_mode": {
126 | "name": "ipython",
127 | "version": 3
128 | },
129 | "file_extension": ".py",
130 | "mimetype": "text/x-python",
131 | "name": "python",
132 | "nbconvert_exporter": "python",
133 | "pygments_lexer": "ipython3",
134 | "version": "3.10.6"
135 | }
136 | },
137 | "nbformat": 4,
138 | "nbformat_minor": 5
139 | }
140 |
--------------------------------------------------------------------------------
/doc/_docstrings/mpl_palette.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "1d0d41d3-463c-4c6f-aa65-38131bdf3ddb",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "sns.palettes._patch_colormap_display()"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "id": "d2a0ae1e-a01e-49b3-a677-2b05a195990a",
22 | "metadata": {},
23 | "source": [
24 | "Return discrete samples from a continuous matplotlib colormap:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "2b6a4ce9-6e4e-4b59-ada8-14ef8aef21d7",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.mpl_palette(\"viridis\")"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "0ccc47b1-c969-46e2-93bb-b9eb5a2e2141",
40 | "metadata": {},
41 | "source": [
42 | "Return the continuous colormap instead; note how the extreme values are more intense:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "a8a1bc5d-1d62-45c6-a53b-9fadb58f11c0",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.mpl_palette(\"viridis\", as_cmap=True)"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "ff0d1a3b-8641-40c0-bb4b-c22b83ec9432",
58 | "metadata": {},
59 | "source": [
60 | "Return more colors:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "8faef1d8-a1eb-4060-be10-377342c9bd1d",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.mpl_palette(\"viridis\", 8)"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "612bf052-e888-411d-a2ea-6a742a78bc63",
76 | "metadata": {},
77 | "source": [
78 | "Return values from a qualitative colormap:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "74db95a8-4898-4f6c-a57d-c751af1dc7bf",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "sns.mpl_palette(\"Set2\")"
89 | ]
90 | },
91 | {
92 | "cell_type": "raw",
93 | "id": "918494bf-1b8e-4b00-8950-1bd73032dee1",
94 | "metadata": {},
95 | "source": [
96 | "Notice how the palette will only contain distinct colors and can be shorter than requested:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "id": "d97efa25-9050-4e28-b758-da6f43c9f963",
103 | "metadata": {},
104 | "outputs": [],
105 | "source": [
106 | "sns.mpl_palette(\"Set2\", 10)"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "id": "f64ad118-e213-43cc-a714-98ed13cc3824",
113 | "metadata": {},
114 | "outputs": [],
115 | "source": []
116 | }
117 | ],
118 | "metadata": {
119 | "kernelspec": {
120 | "display_name": "py310",
121 | "language": "python",
122 | "name": "py310"
123 | },
124 | "language_info": {
125 | "codemirror_mode": {
126 | "name": "ipython",
127 | "version": 3
128 | },
129 | "file_extension": ".py",
130 | "mimetype": "text/x-python",
131 | "name": "python",
132 | "nbconvert_exporter": "python",
133 | "pygments_lexer": "ipython3",
134 | "version": "3.10.6"
135 | }
136 | },
137 | "nbformat": 4,
138 | "nbformat_minor": 5
139 | }
140 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Count.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "89113d6b-70b9-4ebe-9910-10a80eab246e",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "tips = load_dataset(\"tips\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "daf6ff78-df24-4541-ba72-73fb9eddb50d",
22 | "metadata": {},
23 | "source": [
24 | "The transform counts distinct observations of the orientation variable defines a new variable on the opposite axis:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "390f2fd3-0596-40e3-b262-163b3a90d055",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "so.Plot(tips, x=\"day\").add(so.Bar(), so.Count())"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "813fb4a5-db68-4b51-b236-5b5628ebba47",
40 | "metadata": {},
41 | "source": [
42 | "When additional mapping variables are defined, they are also used to define groups:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "76a4ae70-e914-4f54-b979-ce1b79374fc3",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "so.Plot(tips, x=\"day\", color=\"sex\").add(so.Bar(), so.Count(), so.Dodge())"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "2973dee1-5aee-4768-846d-22d220faf170",
58 | "metadata": {},
59 | "source": [
60 | "Unlike :class:`Hist`, numeric data are not binned before counting:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "6f94c5f0-680e-4d8a-a1c9-70876980dd1c",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "so.Plot(tips, x=\"size\").add(so.Bar(), so.Count())"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "11acd5e6-f477-4eb1-b1d7-72f4582bca45",
76 | "metadata": {},
77 | "source": [
78 | "When the `y` variable is defined, the counts are assigned to the `x` variable:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "924e0e35-210f-4f65-83b4-4aebe41ad264",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "so.Plot(tips, y=\"size\").add(so.Bar(), so.Count())"
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": null,
94 | "id": "0229fa39-b6dc-48da-9a25-31e25ed34ebc",
95 | "metadata": {},
96 | "outputs": [],
97 | "source": []
98 | }
99 | ],
100 | "metadata": {
101 | "kernelspec": {
102 | "display_name": "py310",
103 | "language": "python",
104 | "name": "py310"
105 | },
106 | "language_info": {
107 | "codemirror_mode": {
108 | "name": "ipython",
109 | "version": 3
110 | },
111 | "file_extension": ".py",
112 | "mimetype": "text/x-python",
113 | "name": "python",
114 | "nbconvert_exporter": "python",
115 | "pygments_lexer": "ipython3",
116 | "version": "3.10.6"
117 | }
118 | },
119 | "nbformat": 4,
120 | "nbformat_minor": 5
121 | }
122 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Lines.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2923956c-f141-4ecb-ab08-e819099f0fa9",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "seaice = load_dataset(\"seaice\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "09694cb8-4867-49fc-80a6-a4551e50b77e",
22 | "metadata": {},
23 | "source": [
24 | "Like :class:`Line`, the mark draws a connecting line between sorted observations:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "acd5788f-e62b-497c-a109-f0bc02b8cae9",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "so.Plot(seaice, \"Date\", \"Extent\").add(so.Lines())"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "8f982f2d-1119-4842-9860-80b415fd24fe",
40 | "metadata": {},
41 | "source": [
42 | "Compared to :class:`Line`, this mark offers fewer settable properties, but it can have better performance when drawing a large number of lines:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "d4411136-1787-47ca-91f4-4ecba541e575",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "(\n",
53 | " so.Plot(\n",
54 | " x=seaice[\"Date\"].dt.day_of_year,\n",
55 | " y=seaice[\"Extent\"],\n",
56 | " color=seaice[\"Date\"].dt.year\n",
57 | " )\n",
58 | " .facet(seaice[\"Date\"].dt.year.round(-1))\n",
59 | " .add(so.Lines(linewidth=.5, color=\"#bbca\"), col=None)\n",
60 | " .add(so.Lines(linewidth=1))\n",
61 | " .scale(color=\"ch:rot=-.2,light=.7\")\n",
62 | " .layout(size=(8, 4))\n",
63 | " .label(title=\"{}s\".format)\n",
64 | ")"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "id": "aaab3914-77d7-4d09-bdbe-f057a2fe28cf",
71 | "metadata": {},
72 | "outputs": [],
73 | "source": []
74 | }
75 | ],
76 | "metadata": {
77 | "kernelspec": {
78 | "display_name": "py310",
79 | "language": "python",
80 | "name": "py310"
81 | },
82 | "language_info": {
83 | "codemirror_mode": {
84 | "name": "ipython",
85 | "version": 3
86 | },
87 | "file_extension": ".py",
88 | "mimetype": "text/x-python",
89 | "name": "python",
90 | "nbconvert_exporter": "python",
91 | "pygments_lexer": "ipython3",
92 | "version": "3.10.6"
93 | }
94 | },
95 | "nbformat": 4,
96 | "nbformat_minor": 5
97 | }
98 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Norm.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "0bfee8b6-1e3e-499d-96ae-735a5c230b32",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "healthexp = load_dataset(\"healthexp\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "43adf565-2843-48fe-a12a-1a65bc9fce9f",
22 | "metadata": {},
23 | "source": [
24 | "By default, this transform scales each group relative to its maximum value:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "6262c89d-56cd-41b4-8276-0bf737b02f29",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "(\n",
35 | " so.Plot(healthexp, x=\"Year\", y=\"Spending_USD\", color=\"Country\")\n",
36 | " .add(so.Lines(), so.Norm())\n",
37 | " .label(y=\"Spending relative to maximum amount\")\n",
38 | ")"
39 | ]
40 | },
41 | {
42 | "cell_type": "raw",
43 | "id": "5941b47a-7f2f-4540-9944-c6a16e7eec75",
44 | "metadata": {},
45 | "source": [
46 | "Use `where` to constrain the values used to define a baseline, and `percent` to scale the output:"
47 | ]
48 | },
49 | {
50 | "cell_type": "code",
51 | "execution_count": null,
52 | "id": "8142d0b4-1b91-4ba9-bc60-3df148130ff9",
53 | "metadata": {},
54 | "outputs": [],
55 | "source": [
56 | "(\n",
57 | " so.Plot(healthexp, x=\"Year\", y=\"Spending_USD\", color=\"Country\")\n",
58 | " .add(so.Lines(), so.Norm(where=\"x == x.min()\", percent=True))\n",
59 | " .label(y=\"Percent change in spending from 1970 baseline\")\n",
60 | ")"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "2f2d2d33-8a92-44fb-b37a-24dee23a7d75",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": []
70 | }
71 | ],
72 | "metadata": {
73 | "kernelspec": {
74 | "display_name": "py310",
75 | "language": "python",
76 | "name": "py310"
77 | },
78 | "language_info": {
79 | "codemirror_mode": {
80 | "name": "ipython",
81 | "version": 3
82 | },
83 | "file_extension": ".py",
84 | "mimetype": "text/x-python",
85 | "name": "python",
86 | "nbconvert_exporter": "python",
87 | "pygments_lexer": "ipython3",
88 | "version": "3.10.6"
89 | }
90 | },
91 | "nbformat": 4,
92 | "nbformat_minor": 5
93 | }
94 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Path.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2923956c-f141-4ecb-ab08-e819099f0fa9",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "healthexp = load_dataset(\"healthexp\").sort_values([\"Country\", \"Year\"])"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "8c2781ed-190d-4155-99ac-0170b94de030",
22 | "metadata": {},
23 | "source": [
24 | "Unlike :class:`Line`, this mark does not sort observations before plotting, making it suitable for plotting trajectories through a variable space:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "199c0b22-1cbd-4b5a-bebe-f59afa79b9c6",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "p = so.Plot(healthexp, \"Spending_USD\", \"Life_Expectancy\", color=\"Country\")\n",
35 | "p.add(so.Path())"
36 | ]
37 | },
38 | {
39 | "cell_type": "raw",
40 | "id": "fb87bd85-024b-42f5-b458-3550271d7124",
41 | "metadata": {},
42 | "source": [
43 | "It otherwise offers the same set of options, including a number of properties that can be set or mapped:"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": null,
49 | "id": "280de309-1c0d-4cdc-8f4c-a4f15da461cf",
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "p.add(so.Path(marker=\"o\", pointsize=2, linewidth=.75, fillcolor=\"w\"))"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": null,
59 | "id": "4e795770-4481-4e23-a49b-e828a1f5cbbd",
60 | "metadata": {},
61 | "outputs": [],
62 | "source": []
63 | }
64 | ],
65 | "metadata": {
66 | "kernelspec": {
67 | "display_name": "py310",
68 | "language": "python",
69 | "name": "py310"
70 | },
71 | "language_info": {
72 | "codemirror_mode": {
73 | "name": "ipython",
74 | "version": 3
75 | },
76 | "file_extension": ".py",
77 | "mimetype": "text/x-python",
78 | "name": "python",
79 | "nbconvert_exporter": "python",
80 | "pygments_lexer": "ipython3",
81 | "version": "3.10.6"
82 | }
83 | },
84 | "nbformat": 4,
85 | "nbformat_minor": 5
86 | }
87 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Paths.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2923956c-f141-4ecb-ab08-e819099f0fa9",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "networks = (\n",
17 | " load_dataset(\"brain_networks\", header=[0, 1, 2], index_col=0)\n",
18 | " .rename_axis(\"timepoint\")\n",
19 | " .stack([0, 1, 2])\n",
20 | " .groupby([\"timepoint\", \"network\", \"hemi\"])\n",
21 | " .mean()\n",
22 | " .unstack(\"network\")\n",
23 | " .reset_index()\n",
24 | " .query(\"timepoint < 100\")\n",
25 | ")"
26 | ]
27 | },
28 | {
29 | "cell_type": "raw",
30 | "id": "50646936-5236-413f-b79b-6c3b640ade04",
31 | "metadata": {},
32 | "source": [
33 | "Unlike :class:`Lines`, this mark does not sort observations before plotting, making it suitable for plotting trajectories through a variable space:"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": null,
39 | "id": "4a3ed115-cc47-4ea8-be46-2c99f7453941",
40 | "metadata": {},
41 | "outputs": [],
42 | "source": [
43 | "p = (\n",
44 | " so.Plot(networks)\n",
45 | " .pair(\n",
46 | " x=[\"5\", \"8\", \"12\", \"15\"],\n",
47 | " y=[\"6\", \"13\", \"16\"],\n",
48 | " )\n",
49 | " .layout(size=(8, 5))\n",
50 | " .share(x=True, y=True)\n",
51 | ")\n",
52 | "p.add(so.Paths())"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "5bf502eb-feb3-4b2e-882b-3e915bf5d041",
58 | "metadata": {},
59 | "source": [
60 | "The mark has the same set of properties as :class:`Lines`:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "326a765b-59f0-46ef-91c2-6705c6893740",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "p.add(so.Paths(linewidth=1, alpha=.8), color=\"hemi\")"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": null,
76 | "id": "175b836d-d328-4b6c-ad36-dde18c19e3bf",
77 | "metadata": {},
78 | "outputs": [],
79 | "source": []
80 | }
81 | ],
82 | "metadata": {
83 | "kernelspec": {
84 | "display_name": "py310",
85 | "language": "python",
86 | "name": "py310"
87 | },
88 | "language_info": {
89 | "codemirror_mode": {
90 | "name": "ipython",
91 | "version": 3
92 | },
93 | "file_extension": ".py",
94 | "mimetype": "text/x-python",
95 | "name": "python",
96 | "nbconvert_exporter": "python",
97 | "pygments_lexer": "ipython3",
98 | "version": "3.10.6"
99 | }
100 | },
101 | "nbformat": 4,
102 | "nbformat_minor": 5
103 | }
104 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Perc.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2d44a326-029b-47ff-b560-5f4b6a4bb73f",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "diamonds = load_dataset(\"diamonds\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "65e975a2-2559-4bf1-8851-8bbbf52bf22d",
22 | "metadata": {},
23 | "source": [
24 | "The default behavior computes the quartiles and min/max of the input data:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "36f927f5-3b64-4871-a355-adadc4da769b",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "p = (\n",
35 | " so.Plot(diamonds, \"cut\", \"price\")\n",
36 | " .scale(y=\"log\")\n",
37 | ")\n",
38 | "p.add(so.Dot(), so.Perc())"
39 | ]
40 | },
41 | {
42 | "cell_type": "raw",
43 | "id": "feba1b99-0f71-4b18-8e7e-bd5470cc2d0c",
44 | "metadata": {},
45 | "source": [
46 | "Passing an integer will compute that many evenly-spaced percentiles:"
47 | ]
48 | },
49 | {
50 | "cell_type": "code",
51 | "execution_count": null,
52 | "id": "f030dd39-1223-475a-93e1-1759a8971a6c",
53 | "metadata": {},
54 | "outputs": [],
55 | "source": [
56 | "p.add(so.Dot(), so.Perc(20))"
57 | ]
58 | },
59 | {
60 | "cell_type": "raw",
61 | "id": "85bd754b-122e-4475-8727-2d584a90a38e",
62 | "metadata": {},
63 | "source": [
64 | "Passing a list will compute exactly those percentiles:"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "id": "2fde7549-45b5-411a-afba-eb0da754d9e9",
71 | "metadata": {},
72 | "outputs": [],
73 | "source": [
74 | "p.add(so.Dot(), so.Perc([10, 25, 50, 75, 90]))"
75 | ]
76 | },
77 | {
78 | "cell_type": "raw",
79 | "id": "7be16a13-dfc8-4595-a904-42f9be10f4f6",
80 | "metadata": {},
81 | "source": [
82 | "Combine with a range mark to show a percentile interval:"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "id": "05c561c6-0449-4a61-96d1-390611a1b694",
89 | "metadata": {},
90 | "outputs": [],
91 | "source": [
92 | "(\n",
93 | " so.Plot(diamonds, \"price\", \"cut\")\n",
94 | " .add(so.Dots(pointsize=1, alpha=.2), so.Jitter(.3))\n",
95 | " .add(so.Range(color=\"k\"), so.Perc([25, 75]), so.Shift(y=.2))\n",
96 | " .scale(x=\"log\")\n",
97 | ")"
98 | ]
99 | },
100 | {
101 | "cell_type": "code",
102 | "execution_count": null,
103 | "id": "d464157c-3187-49c1-9cd8-71f284ce4c50",
104 | "metadata": {},
105 | "outputs": [],
106 | "source": []
107 | }
108 | ],
109 | "metadata": {
110 | "kernelspec": {
111 | "display_name": "py310",
112 | "language": "python",
113 | "name": "py310"
114 | },
115 | "language_info": {
116 | "codemirror_mode": {
117 | "name": "ipython",
118 | "version": 3
119 | },
120 | "file_extension": ".py",
121 | "mimetype": "text/x-python",
122 | "name": "python",
123 | "nbconvert_exporter": "python",
124 | "pygments_lexer": "ipython3",
125 | "version": "3.10.6"
126 | }
127 | },
128 | "nbformat": 4,
129 | "nbformat_minor": 5
130 | }
131 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Plot.layout.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "9252d5a5-8af1-4f99-b799-ee044329fb23",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "id": "406f8f8d-b590-46f4-a230-626e32e52c71",
20 | "metadata": {},
21 | "source": [
22 | "Control the overall dimensions of the figure with `size`:"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "fefc2b45-3510-4cd7-9de9-4806d71fc4c1",
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "p = so.Plot().layout(size=(4, 4))\n",
33 | "p"
34 | ]
35 | },
36 | {
37 | "cell_type": "raw",
38 | "id": "909a47bb-82f5-455a-99c3-7049d548561b",
39 | "metadata": {},
40 | "source": [
41 | "Subplots created by using :meth:`Plot.facet` or :meth:`Plot.pair` will shrink to fit in the available space:"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "id": "3163687c-8d48-4e88-8dc2-35e16341e30e",
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "p.facet([\"A\", \"B\"], [\"X\", \"Y\"])"
52 | ]
53 | },
54 | {
55 | "cell_type": "markdown",
56 | "id": "feda7c3a-3862-48d4-bb18-419cd03fc081",
57 | "metadata": {},
58 | "source": [
59 | "You may find that different automatic layout engines give better or worse results with specific plots:"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": null,
65 | "id": "c2107939-c6a9-414c-b3a2-6f5d0dd60daf",
66 | "metadata": {},
67 | "outputs": [],
68 | "source": [
69 | "p.facet([\"A\", \"B\"], [\"X\", \"Y\"]).layout(engine=\"constrained\")"
70 | ]
71 | },
72 | {
73 | "cell_type": "markdown",
74 | "id": "d61054d1-dcef-4e11-9802-394bcc633f9f",
75 | "metadata": {},
76 | "source": [
77 | "With `extent`, you can control the size of the plot relative to the underlying figure. Because the notebook display adapts the figure background to the plot, this appears only to change the plot size in a notebook context. But it can be useful when saving or displaying through a `pyplot` GUI window:"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": null,
83 | "id": "1b5d5969-2925-474f-8e3c-99e4f90a7a2b",
84 | "metadata": {},
85 | "outputs": [],
86 | "source": [
87 | "p.layout(extent=[0, 0, .8, 1]).show()"
88 | ]
89 | },
90 | {
91 | "cell_type": "code",
92 | "execution_count": null,
93 | "id": "e5c41b7d-a064-4406-8571-a544b194f3dc",
94 | "metadata": {},
95 | "outputs": [],
96 | "source": []
97 | }
98 | ],
99 | "metadata": {
100 | "kernelspec": {
101 | "display_name": "py310",
102 | "language": "python",
103 | "name": "py310"
104 | },
105 | "language_info": {
106 | "codemirror_mode": {
107 | "name": "ipython",
108 | "version": 3
109 | },
110 | "file_extension": ".py",
111 | "mimetype": "text/x-python",
112 | "name": "python",
113 | "nbconvert_exporter": "python",
114 | "pygments_lexer": "ipython3",
115 | "version": "3.10.6"
116 | }
117 | },
118 | "nbformat": 4,
119 | "nbformat_minor": 5
120 | }
121 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Plot.limit.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "9252d5a5-8af1-4f99-b799-ee044329fb23",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so"
15 | ]
16 | },
17 | {
18 | "cell_type": "raw",
19 | "id": "1888667e-8761-4c32-9510-68e08e64f21d",
20 | "metadata": {},
21 | "source": [
22 | "By default, plot limits are automatically set to provide a small margin around the data (controlled by :meth:`Plot.theme` parameters `axes.xmargin` and `axes.ymargin`):"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "25ec46d9-3c60-4962-b182-a2b2c8310305",
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "p = so.Plot(x=[1, 2, 3], y=[1, 3, 2]).add(so.Line(marker=\"o\"))\n",
33 | "p"
34 | ]
35 | },
36 | {
37 | "cell_type": "raw",
38 | "id": "5f5c19d8-4104-4df0-ae45-9a8ac96d024e",
39 | "metadata": {},
40 | "source": [
41 | "Pass a `min`/`max` tuple to pin the limits at specific values:"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "id": "804388c5-5efa-4cfb-92d8-97fdf838ae5e",
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "p.limit(x=(0, 4), y=(-1, 6))"
52 | ]
53 | },
54 | {
55 | "cell_type": "markdown",
56 | "id": "49634203-4c77-42ae-abc1-b182671f305e",
57 | "metadata": {},
58 | "source": [
59 | "Reversing the `min`/`max` values will invert the axis:"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": null,
65 | "id": "6ea1c82c-a9bc-43cc-ba75-5ee28923b8f2",
66 | "metadata": {},
67 | "outputs": [],
68 | "source": [
69 | "p.limit(y=(4, 0))"
70 | ]
71 | },
72 | {
73 | "cell_type": "raw",
74 | "id": "9bb25c70-3960-4a81-891c-2bd299e7b24f",
75 | "metadata": {},
76 | "source": [
77 | "Use `None` for either side to maintain the default value:"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": null,
83 | "id": "d0566ba8-707c-4808-9a76-525ccaef7a42",
84 | "metadata": {},
85 | "outputs": [],
86 | "source": [
87 | "p.limit(y=(0, None))"
88 | ]
89 | },
90 | {
91 | "cell_type": "code",
92 | "execution_count": null,
93 | "id": "fefc2b45-3510-4cd7-9de9-4806d71fc4c1",
94 | "metadata": {},
95 | "outputs": [],
96 | "source": []
97 | }
98 | ],
99 | "metadata": {
100 | "kernelspec": {
101 | "display_name": "py310",
102 | "language": "python",
103 | "name": "py310"
104 | },
105 | "language_info": {
106 | "codemirror_mode": {
107 | "name": "ipython",
108 | "version": 3
109 | },
110 | "file_extension": ".py",
111 | "mimetype": "text/x-python",
112 | "name": "python",
113 | "nbconvert_exporter": "python",
114 | "pygments_lexer": "ipython3",
115 | "version": "3.10.6"
116 | }
117 | },
118 | "nbformat": 4,
119 | "nbformat_minor": 5
120 | }
121 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Plot.share.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "9252d5a5-8af1-4f99-b799-ee044329fb23",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "penguins = load_dataset(\"penguins\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "3a874676-6b0d-45b1-a227-857a536c5ed2",
22 | "metadata": {},
23 | "source": [
24 | "By default, faceted plots will share all axes:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "615d0765-98c7-4694-8115-a6d1b3557fe7",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "p = (\n",
35 | " so.Plot(penguins, x=\"bill_length_mm\", y=\"bill_depth_mm\")\n",
36 | " .facet(col=\"species\", row=\"sex\")\n",
37 | " .add(so.Dots())\n",
38 | ")\n",
39 | "p"
40 | ]
41 | },
42 | {
43 | "cell_type": "raw",
44 | "id": "8b75feb1-491e-4031-9fcb-619037bd1bfb",
45 | "metadata": {},
46 | "source": [
47 | "Set a coordinate variable to `False` to let each subplot adapt independently:"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": null,
53 | "id": "4c23c570-ca9b-49cc-9aab-7d167218454b",
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "p.share(x=False, y=False)"
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "id": "cc46d8d0-7ab9-44c2-8a28-c656fe86c085",
63 | "metadata": {},
64 | "source": [
65 | "It's also possible to share only across rows or columns:"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": null,
71 | "id": "7cb8136b-9aa3-4c48-bd41-fc0e19fa997c",
72 | "metadata": {},
73 | "outputs": [],
74 | "source": [
75 | "p.share(x=\"col\", y=\"row\")"
76 | ]
77 | },
78 | {
79 | "cell_type": "raw",
80 | "id": "91533aba-45ae-4011-b72c-10f5f79e01d0",
81 | "metadata": {},
82 | "source": [
83 | "This method is also relevant for paired plots, which have different defaults. In this case, you would need to opt *in* to full sharing (although it may not always make sense):"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": null,
89 | "id": "e2b71770-e520-45b9-b41c-a66431f21e1f",
90 | "metadata": {},
91 | "outputs": [],
92 | "source": [
93 | "(\n",
94 | " so.Plot(penguins, y=\"flipper_length_mm\")\n",
95 | " .pair(x=[\"bill_length_mm\", \"bill_depth_mm\"])\n",
96 | " .add(so.Dots())\n",
97 | " .share(x=True)\n",
98 | ")"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "execution_count": null,
104 | "id": "92c29080-8561-4c90-8581-4d435a5f96b9",
105 | "metadata": {},
106 | "outputs": [],
107 | "source": []
108 | }
109 | ],
110 | "metadata": {
111 | "kernelspec": {
112 | "display_name": "py310",
113 | "language": "python",
114 | "name": "py310"
115 | },
116 | "language_info": {
117 | "codemirror_mode": {
118 | "name": "ipython",
119 | "version": 3
120 | },
121 | "file_extension": ".py",
122 | "mimetype": "text/x-python",
123 | "name": "python",
124 | "nbconvert_exporter": "python",
125 | "pygments_lexer": "ipython3",
126 | "version": "3.10.6"
127 | }
128 | },
129 | "nbformat": 4,
130 | "nbformat_minor": 5
131 | }
132 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Shift.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "2605c8d0-5872-4dff-9172-db81fac1cee1",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "penguins = load_dataset(\"penguins\")\n",
17 | "diamonds = load_dataset(\"diamonds\")"
18 | ]
19 | },
20 | {
21 | "cell_type": "raw",
22 | "id": "e70d701a-cd7c-4b38-aaa0-4729e2be56d9",
23 | "metadata": {},
24 | "source": [
25 | "Use this transform to layer multiple marks that would otherwise overlap and be hard to interpret:"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": null,
31 | "id": "5ea7a2c4-cb69-4ad0-8ea8-73067b756371",
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "(\n",
36 | " so.Plot(penguins, \"species\", \"body_mass_g\")\n",
37 | " .add(so.Dots(), so.Jitter())\n",
38 | " .add(so.Range(), so.Perc([25, 75]), so.Shift(x=.2))\n",
39 | ")"
40 | ]
41 | },
42 | {
43 | "cell_type": "raw",
44 | "id": "940b87b2-04fb-40ba-a62f-52f461039ab9",
45 | "metadata": {},
46 | "source": [
47 | "For y variables with a nominal scale, bear in mind that the axis will be inverted and a positive shift will move downwards:"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": null,
53 | "id": "54b5f728-4fbc-474a-8865-0f58d0ad9b0b",
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "(\n",
58 | " so.Plot(diamonds, \"carat\", \"clarity\")\n",
59 | " .add(so.Dots(), so.Jitter())\n",
60 | " .add(so.Range(), so.Perc([25, 75]), so.Shift(y=.25))\n",
61 | ")"
62 | ]
63 | },
64 | {
65 | "cell_type": "code",
66 | "execution_count": null,
67 | "id": "78d9bb6a-ea3d-491e-b43e-25efd386bd59",
68 | "metadata": {},
69 | "outputs": [],
70 | "source": []
71 | }
72 | ],
73 | "metadata": {
74 | "kernelspec": {
75 | "display_name": "py310",
76 | "language": "python",
77 | "name": "py310"
78 | },
79 | "language_info": {
80 | "codemirror_mode": {
81 | "name": "ipython",
82 | "version": 3
83 | },
84 | "file_extension": ".py",
85 | "mimetype": "text/x-python",
86 | "name": "python",
87 | "nbconvert_exporter": "python",
88 | "pygments_lexer": "ipython3",
89 | "version": "3.10.6"
90 | }
91 | },
92 | "nbformat": 4,
93 | "nbformat_minor": 5
94 | }
95 |
--------------------------------------------------------------------------------
/doc/_docstrings/objects.Stack.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "87244f49-8cf2-4668-a556-a8c7828b31bf",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn.objects as so\n",
15 | "from seaborn import load_dataset\n",
16 | "titanic = load_dataset(\"titanic\").sort_values(\"alive\", ascending=False)"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "c9a1a7db-f365-4c5f-85ae-1f00e15b0af9",
22 | "metadata": {},
23 | "source": [
24 | "This transform applies a vertical shift to eliminate overlap between marks with a baseline, such as :class:`Bar` or :class:`Area`:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "07579f71-842d-4dc1-98ab-38652409238d",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "so.Plot(titanic, x=\"class\", color=\"sex\").add(so.Bar(), so.Count(), so.Stack())"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "2488a821-3bf1-4bb9-9963-bf726d11925c",
40 | "metadata": {},
41 | "source": [
42 | "Stacking can make it much harder to compare values between groups that get shifted, but it can work well when depicting a part-whole relationship:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "dcb8ea58-3cf2-455b-b6b7-98b434f2f152",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "(\n",
53 | " so.Plot(titanic, x=\"age\", alpha=\"alive\")\n",
54 | " .facet(\"sex\")\n",
55 | " .add(so.Bars(), so.Hist(binwidth=10), so.Stack())\n",
56 | ")"
57 | ]
58 | },
59 | {
60 | "cell_type": "code",
61 | "execution_count": null,
62 | "id": "b649198f-898e-4103-84bc-d74de71de5a7",
63 | "metadata": {},
64 | "outputs": [],
65 | "source": []
66 | }
67 | ],
68 | "metadata": {
69 | "kernelspec": {
70 | "display_name": "py310",
71 | "language": "python",
72 | "name": "py310"
73 | },
74 | "language_info": {
75 | "codemirror_mode": {
76 | "name": "ipython",
77 | "version": 3
78 | },
79 | "file_extension": ".py",
80 | "mimetype": "text/x-python",
81 | "name": "python",
82 | "nbconvert_exporter": "python",
83 | "pygments_lexer": "ipython3",
84 | "version": "3.10.6"
85 | }
86 | },
87 | "nbformat": 4,
88 | "nbformat_minor": 5
89 | }
90 |
--------------------------------------------------------------------------------
/doc/_docstrings/plotting_context.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "perceived-worry",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "id": "seventh-volleyball",
20 | "metadata": {},
21 | "source": [
22 | "Calling with no arguments will return the current defaults for the parameters that get scaled:"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "roman-villa",
29 | "metadata": {
30 | "tags": [
31 | "show-output"
32 | ]
33 | },
34 | "outputs": [],
35 | "source": [
36 | "sns.plotting_context()"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "id": "handled-texas",
42 | "metadata": {},
43 | "source": [
44 | "Calling with the name of a predefined style will show those values:"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": null,
50 | "id": "distant-caribbean",
51 | "metadata": {
52 | "tags": [
53 | "show-output"
54 | ]
55 | },
56 | "outputs": [],
57 | "source": [
58 | "sns.plotting_context(\"talk\")"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "id": "lightweight-anime",
64 | "metadata": {},
65 | "source": [
66 | "Use the function as a context manager to temporarily change the parameter values:"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": null,
72 | "id": "contemporary-hampshire",
73 | "metadata": {},
74 | "outputs": [],
75 | "source": [
76 | "with sns.plotting_context(\"talk\"):\n",
77 | " sns.lineplot(x=[\"A\", \"B\", \"C\"], y=[1, 3, 2])"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": null,
83 | "id": "accompanied-brisbane",
84 | "metadata": {},
85 | "outputs": [],
86 | "source": []
87 | }
88 | ],
89 | "metadata": {
90 | "kernelspec": {
91 | "display_name": "py310",
92 | "language": "python",
93 | "name": "py310"
94 | },
95 | "language_info": {
96 | "codemirror_mode": {
97 | "name": "ipython",
98 | "version": 3
99 | },
100 | "file_extension": ".py",
101 | "mimetype": "text/x-python",
102 | "name": "python",
103 | "nbconvert_exporter": "python",
104 | "pygments_lexer": "ipython3",
105 | "version": "3.10.6"
106 | }
107 | },
108 | "nbformat": 4,
109 | "nbformat_minor": 5
110 | }
111 |
--------------------------------------------------------------------------------
/doc/_docstrings/residplot.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "776f8271-21ed-4707-a1ad-09d8c63ae95a",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns\n",
15 | "sns.set_theme()\n",
16 | "mpg = sns.load_dataset(\"mpg\")"
17 | ]
18 | },
19 | {
20 | "cell_type": "raw",
21 | "id": "85717971-adc9-45b0-9c4b-3f022d96179c",
22 | "metadata": {},
23 | "source": [
24 | "Pass `x` and `y` to see a scatter plot of the residuals after fitting a simple regression model:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "5aea4655-fb51-4b51-b41d-4769de50e956",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "sns.residplot(data=mpg, x=\"weight\", y=\"displacement\")"
35 | ]
36 | },
37 | {
38 | "cell_type": "raw",
39 | "id": "175b6287-9240-493f-94bc-9d18258e952b",
40 | "metadata": {},
41 | "source": [
42 | "Structure in the residual plot can reveal a violation of linear regression assumptions:"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": null,
48 | "id": "39aa84c2-d623-44be-9b0b-746f52b55fd4",
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.residplot(data=mpg, x=\"horsepower\", y=\"mpg\")"
53 | ]
54 | },
55 | {
56 | "cell_type": "raw",
57 | "id": "bd9641e4-8df5-4751-b261-6443888fbbfe",
58 | "metadata": {},
59 | "source": [
60 | "Remove higher-order trends to test whether that stabilizes the residuals:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "03a68199-1272-464b-8b85-7a309c22a4a6",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.residplot(data=mpg, x=\"horsepower\", y=\"mpg\", order=2)"
71 | ]
72 | },
73 | {
74 | "cell_type": "raw",
75 | "id": "b17750af-0393-4c53-8057-bf95d0de821a",
76 | "metadata": {},
77 | "source": [
78 | "Adding a LOWESS curve can help reveal or emphasize structure:"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "id": "494359bd-47b2-426e-9c35-14b5351eec93",
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "sns.residplot(data=mpg, x=\"horsepower\", y=\"mpg\", lowess=True, line_kws=dict(color=\"r\"))"
89 | ]
90 | }
91 | ],
92 | "metadata": {
93 | "kernelspec": {
94 | "display_name": "py310",
95 | "language": "python",
96 | "name": "py310"
97 | },
98 | "language_info": {
99 | "codemirror_mode": {
100 | "name": "ipython",
101 | "version": 3
102 | },
103 | "file_extension": ".py",
104 | "mimetype": "text/x-python",
105 | "name": "python",
106 | "nbconvert_exporter": "python",
107 | "pygments_lexer": "ipython3",
108 | "version": "3.10.6"
109 | }
110 | },
111 | "nbformat": 4,
112 | "nbformat_minor": 5
113 | }
114 |
--------------------------------------------------------------------------------
/doc/_docstrings/rugplot.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "Add a rug along one of the axes:"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import seaborn as sns; sns.set_theme()\n",
17 | "tips = sns.load_dataset(\"tips\")\n",
18 | "sns.kdeplot(data=tips, x=\"total_bill\")\n",
19 | "sns.rugplot(data=tips, x=\"total_bill\")"
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {},
25 | "source": [
26 | "Add a rug along both axes:"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "sns.scatterplot(data=tips, x=\"total_bill\", y=\"tip\")\n",
36 | "sns.rugplot(data=tips, x=\"total_bill\", y=\"tip\")"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "Represent a third variable with hue mapping:"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": null,
49 | "metadata": {},
50 | "outputs": [],
51 | "source": [
52 | "sns.scatterplot(data=tips, x=\"total_bill\", y=\"tip\", hue=\"time\")\n",
53 | "sns.rugplot(data=tips, x=\"total_bill\", y=\"tip\", hue=\"time\")"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {},
59 | "source": [
60 | "Draw a taller rug:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "metadata": {},
67 | "outputs": [],
68 | "source": [
69 | "sns.scatterplot(data=tips, x=\"total_bill\", y=\"tip\")\n",
70 | "sns.rugplot(data=tips, x=\"total_bill\", y=\"tip\", height=.1)"
71 | ]
72 | },
73 | {
74 | "cell_type": "markdown",
75 | "metadata": {},
76 | "source": [
77 | "Put the rug outside the axes:"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": null,
83 | "metadata": {},
84 | "outputs": [],
85 | "source": [
86 | "sns.scatterplot(data=tips, x=\"total_bill\", y=\"tip\")\n",
87 | "sns.rugplot(data=tips, x=\"total_bill\", y=\"tip\", height=-.02, clip_on=False)"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "metadata": {},
93 | "source": [
94 | "Show the density of a larger dataset using thinner lines and alpha blending:"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": null,
100 | "metadata": {},
101 | "outputs": [],
102 | "source": [
103 | "diamonds = sns.load_dataset(\"diamonds\")\n",
104 | "sns.scatterplot(data=diamonds, x=\"carat\", y=\"price\", s=5)\n",
105 | "sns.rugplot(data=diamonds, x=\"carat\", y=\"price\", lw=1, alpha=.005)"
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "metadata": {},
112 | "outputs": [],
113 | "source": []
114 | }
115 | ],
116 | "metadata": {
117 | "kernelspec": {
118 | "display_name": "py310",
119 | "language": "python",
120 | "name": "py310"
121 | },
122 | "language_info": {
123 | "codemirror_mode": {
124 | "name": "ipython",
125 | "version": 3
126 | },
127 | "file_extension": ".py",
128 | "mimetype": "text/x-python",
129 | "name": "python",
130 | "nbconvert_exporter": "python",
131 | "pygments_lexer": "ipython3",
132 | "version": "3.10.6"
133 | }
134 | },
135 | "nbformat": 4,
136 | "nbformat_minor": 4
137 | }
138 |
--------------------------------------------------------------------------------
/doc/_docstrings/set_context.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "thorough-equipment",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "id": "canadian-protection",
20 | "metadata": {},
21 | "source": [
22 | "Call the function with the name of a context to set the default for all plots:"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "freelance-leonard",
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "sns.set_context(\"notebook\")\n",
33 | "sns.lineplot(x=[0, 1, 2], y=[1, 3, 2])"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "id": "studied-adventure",
39 | "metadata": {},
40 | "source": [
41 | "You can independently scale the font elements relative to the current context:"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "id": "irish-digest",
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "sns.set_context(\"notebook\", font_scale=1.25)\n",
52 | "sns.lineplot(x=[0, 1, 2], y=[1, 3, 2])"
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "id": "fourth-technical",
58 | "metadata": {},
59 | "source": [
60 | "It is also possible to override some of the parameters with specific values:"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": null,
66 | "id": "advance-request",
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "sns.set_context(\"notebook\", rc={\"lines.linewidth\": 3})\n",
71 | "sns.lineplot(x=[0, 1, 2], y=[1, 3, 2])"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": null,
77 | "id": "compatible-string",
78 | "metadata": {},
79 | "outputs": [],
80 | "source": []
81 | }
82 | ],
83 | "metadata": {
84 | "kernelspec": {
85 | "display_name": "py310",
86 | "language": "python",
87 | "name": "py310"
88 | },
89 | "language_info": {
90 | "codemirror_mode": {
91 | "name": "ipython",
92 | "version": 3
93 | },
94 | "file_extension": ".py",
95 | "mimetype": "text/x-python",
96 | "name": "python",
97 | "nbconvert_exporter": "python",
98 | "pygments_lexer": "ipython3",
99 | "version": "3.10.6"
100 | }
101 | },
102 | "nbformat": 4,
103 | "nbformat_minor": 5
104 | }
105 |
--------------------------------------------------------------------------------
/doc/_docstrings/set_style.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "practical-announcement",
7 | "metadata": {
8 | "tags": [
9 | "hide"
10 | ]
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import seaborn as sns"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "id": "suffering-emerald",
20 | "metadata": {},
21 | "source": [
22 | "Call the function with the name of a seaborn style to set the default for all plots:"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "id": "collaborative-struggle",
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "sns.set_style(\"whitegrid\")\n",
33 | "sns.barplot(x=[\"A\", \"B\", \"C\"], y=[1, 3, 2])"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "id": "defensive-surgery",
39 | "metadata": {},
40 | "source": [
41 | "You can also selectively override seaborn's default parameter values:"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "id": "coastal-sydney",
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "sns.set_style(\"darkgrid\", {\"grid.color\": \".6\", \"grid.linestyle\": \":\"})\n",
52 | "sns.lineplot(x=[\"A\", \"B\", \"C\"], y=[1, 3, 2])"
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": null,
58 | "id": "bright-october",
59 | "metadata": {},
60 | "outputs": [],
61 | "source": []
62 | }
63 | ],
64 | "metadata": {
65 | "kernelspec": {
66 | "display_name": "py310",
67 | "language": "python",
68 | "name": "py310"
69 | },
70 | "language_info": {
71 | "codemirror_mode": {
72 | "name": "ipython",
73 | "version": 3
74 | },
75 | "file_extension": ".py",
76 | "mimetype": "text/x-python",
77 | "name": "python",
78 | "nbconvert_exporter": "python",
79 | "pygments_lexer": "ipython3",
80 | "version": "3.10.6"
81 | }
82 | },
83 | "nbformat": 4,
84 | "nbformat_minor": 5
85 | }
86 |
--------------------------------------------------------------------------------
/doc/_static/copybutton.js:
--------------------------------------------------------------------------------
1 | // originally taken from scikit-learn's Sphinx theme
2 | $(document).ready(function() {
3 | /* Add a [>>>] button on the top-right corner of code samples to hide
4 | * the >>> and ... prompts and the output and thus make the code
5 | * copyable.
6 | * Note: This JS snippet was taken from the official python.org
7 | * documentation site.*/
8 | var div = $('.highlight-python .highlight,' +
9 | '.highlight-python3 .highlight,' +
10 | '.highlight-pycon .highlight')
11 | var pre = div.find('pre');
12 |
13 | // get the styles from the current theme
14 | pre.parent().parent().css('position', 'relative');
15 | var hide_text = 'Hide the prompts and output';
16 | var show_text = 'Show the prompts and output';
17 | var border_width = pre.css('border-top-width');
18 | var border_style = pre.css('border-top-style');
19 | var border_color = pre.css('border-top-color');
20 | var button_styles = {
21 | 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
22 | 'border-color': border_color, 'border-style': border_style,
23 | 'border-width': border_width, 'color': border_color, 'text-size': '75%',
24 | 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em'
25 | }
26 |
27 | // create and add the button to all the code blocks that contain >>>
28 | div.each(function(index) {
29 | var jthis = $(this);
30 | if (jthis.find('.gp').length > 0) {
31 | var button = $('>>>');
32 | button.css(button_styles)
33 | button.attr('title', hide_text);
34 | jthis.prepend(button);
35 | }
36 | // tracebacks (.gt) contain bare text elements that need to be
37 | // wrapped in a span to work with .nextUntil() (see later)
38 | jthis.find('pre:has(.gt)').contents().filter(function() {
39 | return ((this.nodeType == 3) && (this.data.trim().length > 0));
40 | }).wrap('');
41 | });
42 |
43 | // define the behavior of the button when it's clicked
44 | $('.copybutton').toggle(
45 | function() {
46 | var button = $(this);
47 | button.parent().find('.go, .gp, .gt').hide();
48 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
49 | button.css('text-decoration', 'line-through');
50 | button.attr('title', show_text);
51 | },
52 | function() {
53 | var button = $(this);
54 | button.parent().find('.go, .gp, .gt').show();
55 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
56 | button.css('text-decoration', 'none');
57 | button.attr('title', hide_text);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/doc/_static/css/custom.css:
--------------------------------------------------------------------------------
1 | /**** Overriding theme defaults ****/
2 |
3 | html[data-theme=light]{
4 | --pst-color-primary: rgb(52, 54, 99);
5 | --pst-color-secondary: rgb(107, 161, 174);
6 | --pst-color-link: rgb(74, 105, 145);
7 | --pst-color-inline-code: rgb(96, 141, 130);
8 | }
9 |
10 | :root {
11 | --pst-font-size-h1: 38px;
12 | --pst-font-size-h2: 32px;
13 | --pst-font-size-h3: 27px;
14 | --pst-font-size-h4: 22px;
15 | --pst-font-size-h5: 18px;
16 | --pst-font-size-h6: 15px;
17 |
18 | }
19 |
20 | /* Syntax highlighting */
21 |
22 | /* string literals */
23 | html[data-theme=light] .highlight .s2 {
24 | color: rgb(74, 105, 145);
25 | font-weight: normal;
26 | }
27 | /* number literals */
28 | html[data-theme=light] .highlight .mi {
29 | color: rgb(136, 97, 153);
30 | font-weight: normal;
31 | }
32 | html[data-theme=light] .highlight .mf {
33 | color: rgb(136, 97, 153);
34 | font-weight: normal;
35 | }
36 | /* operators */
37 | html[data-theme=light] .highlight .o {
38 | color: rgb(219, 164, 117);
39 | font-weight: bold;
40 | }
41 | /* builtins */
42 | html[data-theme=light] .highlight .kc {
43 | color: rgb(107, 161, 174);
44 | font-weight: bold;
45 | }
46 |
47 | /* Use full page width without sidebars */
48 | .bd-content {
49 | max-width: 100%;
50 | flex-grow: 1;
51 | }
52 |
53 | /* Function signature customization */
54 | dt {
55 | font-weight: 500;
56 | color: rgb(52, 54, 99);
57 | }
58 |
59 | span.default_value {
60 | color: rgb(124, 141, 138);
61 | }
62 |
63 | /* highlight over function signature after link */
64 | dt:target, span.highlighted {
65 | background-color: #fdebba;
66 | }
67 |
68 | /* *********************************************************************** */
69 |
70 | /* --- Badges for categorizing release notes --- */
71 |
72 | .label,
73 | .badge {
74 | display: inline-block;
75 | padding: 2px 4px;
76 | font-size: 11.844px;
77 | /* font-weight: bold; */
78 | line-height: 13px;
79 | color: #ffffff;
80 | vertical-align: baseline;
81 | white-space: nowrap;
82 | /* text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); */
83 | background-color: #999999;
84 | }
85 | .badge {
86 | padding-left: 9px;
87 | padding-right: 9px;
88 | -webkit-border-radius: 9px;
89 | -moz-border-radius: 9px;
90 | border-radius: 9px;
91 | opacity: 70%;
92 | }
93 | .badge-api {
94 | background-color: #c44e52;
95 | }
96 | .badge-defaults {
97 | background-color: #dd8452;
98 | }
99 | .badge-docs {
100 | background-color: #8172b3;
101 | }
102 | .badge-feature {
103 | background-color: #55a868;
104 | }
105 | .badge-enhancement {
106 | background-color: #4c72b0;
107 | }
108 | .badge-fix {
109 | background-color: #ccb974;
110 | }
111 | .badge-build {
112 | background-color: #937860;
113 | }
114 |
--------------------------------------------------------------------------------
/doc/_static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/favicon.ico
--------------------------------------------------------------------------------
/doc/_static/favicon_old.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/favicon_old.ico
--------------------------------------------------------------------------------
/doc/_static/logo-mark-darkbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-mark-darkbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-mark-lightbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-mark-lightbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-mark-whitebg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-mark-whitebg.png
--------------------------------------------------------------------------------
/doc/_static/logo-tall-darkbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-tall-darkbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-tall-lightbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-tall-lightbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-tall-whitebg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-tall-whitebg.png
--------------------------------------------------------------------------------
/doc/_static/logo-wide-darkbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-wide-darkbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-wide-lightbg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-wide-lightbg.png
--------------------------------------------------------------------------------
/doc/_static/logo-wide-whitebg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/_static/logo-wide-whitebg.png
--------------------------------------------------------------------------------
/doc/_templates/autosummary/base.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. auto{{ objtype }}:: {{ objname }}
6 |
--------------------------------------------------------------------------------
/doc/_templates/autosummary/class.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 |
7 | {% block methods %}
8 | .. automethod:: __init__
9 |
10 | {% if methods %}
11 | .. rubric:: Methods
12 |
13 | .. autosummary::
14 | :toctree: ./
15 | {% for item in methods %}
16 | ~{{ name }}.{{ item }}
17 | {%- endfor %}
18 | {% endif %}
19 | {% endblock %}
20 |
21 | {% block attributes %}
22 | {% if attributes %}
23 | .. rubric:: Attributes
24 |
25 | .. autosummary::
26 | {% for item in attributes %}
27 | ~{{ name }}.{{ item }}
28 | {%- endfor %}
29 | {% endif %}
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/doc/_templates/autosummary/object.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 |
--------------------------------------------------------------------------------
/doc/_templates/autosummary/plot.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 |
7 | {% block methods %}
8 |
9 | Methods
10 | ~~~~~~~
11 |
12 | .. rubric:: Specification methods
13 |
14 | .. autosummary::
15 | :toctree: ./
16 | :nosignatures:
17 |
18 | ~Plot.add
19 | ~Plot.scale
20 |
21 | .. rubric:: Subplot methods
22 |
23 | .. autosummary::
24 | :toctree: ./
25 | :nosignatures:
26 |
27 | ~Plot.facet
28 | ~Plot.pair
29 |
30 | .. rubric:: Customization methods
31 |
32 | .. autosummary::
33 | :toctree: ./
34 | :nosignatures:
35 |
36 | ~Plot.layout
37 | ~Plot.label
38 | ~Plot.limit
39 | ~Plot.share
40 | ~Plot.theme
41 |
42 | .. rubric:: Integration methods
43 |
44 | .. autosummary::
45 | :toctree: ./
46 | :nosignatures:
47 |
48 | ~Plot.on
49 |
50 | .. rubric:: Output methods
51 |
52 | .. autosummary::
53 | :toctree: ./
54 | :nosignatures:
55 |
56 | ~Plot.plot
57 | ~Plot.save
58 | ~Plot.show
59 |
60 | {% endblock %}
61 |
62 | .. _plot_config:
63 |
64 | Configuration
65 | ~~~~~~~~~~~~~
66 |
67 | The :class:`Plot` object's default behavior can be configured through its :attr:`Plot.config` attribute. Notice that this is a property of the class, not a method on an instance.
68 |
69 | .. include:: ../docstrings/objects.Plot.config.rst
70 |
--------------------------------------------------------------------------------
/doc/_templates/autosummary/scale.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 |
7 | .. automethod:: tick
8 |
9 | .. automethod:: label
10 |
--------------------------------------------------------------------------------
/doc/_templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "!layout.html" %}
2 |
3 | {%- block footer %}
4 |
27 | {%- endblock %}
28 |
--------------------------------------------------------------------------------
/doc/_templates/version.html:
--------------------------------------------------------------------------------
1 |
2 | {{ version }}
3 |
4 |
--------------------------------------------------------------------------------
/doc/_tutorial/Makefile:
--------------------------------------------------------------------------------
1 | rst_files := $(patsubst %.ipynb,../tutorial/%.rst,$(wildcard *.ipynb))
2 | export MPLBACKEND := module://matplotlib_inline.backend_inline
3 |
4 | tutorial: ${rst_files}
5 |
6 | ../tutorial/%.rst: %.ipynb
7 | ../tools/nb_to_doc.py $*.ipynb ../tutorial
8 |
9 | clean:
10 | rm -rf ../tutorial
11 |
--------------------------------------------------------------------------------
/doc/citing.rst:
--------------------------------------------------------------------------------
1 | .. _citing:
2 |
3 | Citing and logo
4 | ===============
5 |
6 | Citing seaborn
7 | --------------
8 |
9 | If seaborn is integral to a scientific publication, please cite it.
10 | A paper describing seaborn has been published in the `Journal of Open Source Software `_:
11 |
12 | Waskom, M. L., (2021). seaborn: statistical data visualization. Journal of Open Source Software, 6(60), 3021, https://doi.org/10.21105/joss.03021.
13 |
14 | Here is a ready-made BibTeX entry:
15 |
16 | .. highlight:: none
17 |
18 | ::
19 |
20 | @article{Waskom2021,
21 | doi = {10.21105/joss.03021},
22 | url = {https://doi.org/10.21105/joss.03021},
23 | year = {2021},
24 | publisher = {The Open Journal},
25 | volume = {6},
26 | number = {60},
27 | pages = {3021},
28 | author = {Michael L. Waskom},
29 | title = {seaborn: statistical data visualization},
30 | journal = {Journal of Open Source Software}
31 | }
32 |
33 | In most situations where seaborn is cited, a citation to `matplotlib `_ would also be appropriate.
34 |
35 | Logo files
36 | ----------
37 |
38 | Additional logo files, including hi-res PNGs and images suitable for use over a dark background, are available
39 | `on GitHub `_.
40 |
41 | Wide logo
42 | ~~~~~~~~~
43 |
44 | .. image:: _static/logo-wide-lightbg.svg
45 | :width: 400px
46 |
47 | Tall logo
48 | ~~~~~~~~~
49 |
50 | .. image:: _static/logo-tall-lightbg.svg
51 | :width: 150px
52 |
53 | Logo mark
54 | ~~~~~~~~~
55 |
56 | .. image:: _static/logo-mark-lightbg.svg
57 | :width: 150px
58 |
59 | Credit to `Matthias Bussonnier `_ for the initial design
60 | and implementation of the logo.
61 |
--------------------------------------------------------------------------------
/doc/example_thumbs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/doc/example_thumbs/.gitkeep
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | :html_theme.sidebar_secondary.remove:
2 |
3 | seaborn: statistical data visualization
4 | =======================================
5 |
6 | .. grid:: 6
7 | :gutter: 1
8 |
9 | .. grid-item::
10 |
11 | .. image:: example_thumbs/scatterplot_matrix_thumb.png
12 | :target: ./examples/scatterplot_matrix.html
13 |
14 | .. grid-item::
15 |
16 | .. image:: example_thumbs/errorband_lineplots_thumb.png
17 | :target: examples/errorband_lineplots.html
18 |
19 | .. grid-item::
20 |
21 | .. image:: example_thumbs/scatterplot_sizes_thumb.png
22 | :target: examples/scatterplot_sizes.html
23 |
24 | .. grid-item::
25 |
26 | .. image:: example_thumbs/timeseries_facets_thumb.png
27 | :target: examples/timeseries_facets.html
28 |
29 | .. grid-item::
30 |
31 | .. image:: example_thumbs/horizontal_boxplot_thumb.png
32 | :target: examples/horizontal_boxplot.html
33 |
34 | .. grid-item::
35 |
36 | .. image:: example_thumbs/regression_marginals_thumb.png
37 | :target: examples/regression_marginals.html
38 |
39 | .. grid:: 1 1 3 3
40 |
41 | .. grid-item::
42 | :columns: 12 12 6 6
43 |
44 | Seaborn is a Python data visualization library based on `matplotlib
45 | `_. It provides a high-level interface for drawing
46 | attractive and informative statistical graphics.
47 |
48 | For a brief introduction to the ideas behind the library, you can read the
49 | :doc:`introductory notes ` or the `paper
50 | `_. Visit the
51 | :doc:`installation page ` to see how you can download the package
52 | and get started with it. You can browse the :doc:`example gallery
53 | ` to see some of the things that you can do with seaborn,
54 | and then check out the :doc:`tutorials ` or :doc:`API reference `
55 | to find out how.
56 |
57 | To see the code or report a bug, please visit the `GitHub repository
58 | `_. General support questions are most at home
59 | on `stackoverflow `_, which
60 | has a dedicated channel for seaborn.
61 |
62 | .. grid-item-card:: Contents
63 | :columns: 12 12 2 2
64 | :class-title: sd-fs-5
65 | :class-body: sd-pl-4
66 |
67 | .. toctree::
68 | :maxdepth: 1
69 |
70 | Installing
71 | Gallery
72 | Tutorial
73 | API
74 | Releases
75 | Citing
76 | FAQ
77 |
78 | .. grid-item-card:: Features
79 | :columns: 12 12 4 4
80 | :class-title: sd-fs-5
81 | :class-body: sd-pl-3
82 |
83 | * :bdg-secondary:`New` Objects: :ref:`API ` | :doc:`Tutorial `
84 | * Relational plots: :ref:`API ` | :doc:`Tutorial `
85 | * Distribution plots: :ref:`API ` | :doc:`Tutorial `
86 | * Categorical plots: :ref:`API ` | :doc:`Tutorial `
87 | * Regression plots: :ref:`API ` | :doc:`Tutorial `
88 | * Multi-plot grids: :ref:`API ` | :doc:`Tutorial `
89 | * Figure theming: :ref:`API ` | :doc:`Tutorial `
90 | * Color palettes: :ref:`API ` | :doc:`Tutorial `
91 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/doc/matplotlibrc:
--------------------------------------------------------------------------------
1 | savefig.bbox : tight
2 |
--------------------------------------------------------------------------------
/doc/tools/extract_examples.py:
--------------------------------------------------------------------------------
1 | """Turn the examples section of a function docstring into a notebook."""
2 | import re
3 | import sys
4 | import pydoc
5 | import seaborn
6 | from seaborn.external.docscrape import NumpyDocString
7 | import nbformat
8 |
9 |
10 | def line_type(line):
11 |
12 | if line.startswith(" "):
13 | return "code"
14 | else:
15 | return "markdown"
16 |
17 |
18 | def add_cell(nb, lines, cell_type):
19 |
20 | cell_objs = {
21 | "code": nbformat.v4.new_code_cell,
22 | "markdown": nbformat.v4.new_markdown_cell,
23 | }
24 | text = "\n".join(lines)
25 | cell = cell_objs[cell_type](text)
26 | nb["cells"].append(cell)
27 |
28 |
29 | if __name__ == "__main__":
30 |
31 | _, name = sys.argv
32 |
33 | # Parse the docstring and get the examples section
34 | obj = getattr(seaborn, name)
35 | if obj.__class__.__name__ != "function":
36 | obj = obj.__init__
37 | lines = NumpyDocString(pydoc.getdoc(obj))["Examples"]
38 |
39 | # Remove code indentation, the prompt, and mpl return variable
40 | pat = re.compile(r"\s{4}[>\.]{3} (ax = ){0,1}(g = ){0,1}")
41 |
42 | nb = nbformat.v4.new_notebook()
43 |
44 | # We always start with at least one line of text
45 | cell_type = "markdown"
46 | cell = []
47 |
48 | for line in lines:
49 |
50 | # Ignore matplotlib plot directive
51 | if ".. plot" in line or ":context:" in line:
52 | continue
53 |
54 | # Ignore blank lines
55 | if not line:
56 | continue
57 |
58 | if line_type(line) != cell_type:
59 | # We are on the first line of the next cell,
60 | # so package up the last cell
61 | add_cell(nb, cell, cell_type)
62 | cell_type = line_type(line)
63 | cell = []
64 |
65 | if line_type(line) == "code":
66 | line = re.sub(pat, "", line)
67 |
68 | cell.append(line)
69 |
70 | # Package the final cell
71 | add_cell(nb, cell, cell_type)
72 |
73 | nbformat.write(nb, f"docstrings/{name}.ipynb")
74 |
--------------------------------------------------------------------------------
/doc/tools/set_nb_kernels.py:
--------------------------------------------------------------------------------
1 | """Recursively set the kernel name for all jupyter notebook files."""
2 | import sys
3 | from glob import glob
4 |
5 | import nbformat
6 |
7 |
8 | if __name__ == "__main__":
9 |
10 | _, kernel_name = sys.argv
11 |
12 | nb_paths = glob("./**/*.ipynb", recursive=True)
13 | for path in nb_paths:
14 |
15 | with open(path) as f:
16 | nb = nbformat.read(f, as_version=4)
17 |
18 | nb["metadata"]["kernelspec"]["name"] = kernel_name
19 | nb["metadata"]["kernelspec"]["display_name"] = kernel_name
20 |
21 | with open(path, "w") as f:
22 | nbformat.write(nb, f)
23 |
--------------------------------------------------------------------------------
/doc/tutorial.yaml:
--------------------------------------------------------------------------------
1 | - title:
2 | pages:
3 | - introduction
4 | - title: API Overview
5 | pages:
6 | - function_overview
7 | - data_structure
8 | - title: Objects interface
9 | pages:
10 | - objects_interface
11 | - properties
12 | - title: Plotting functions
13 | pages:
14 | - relational
15 | - distributions
16 | - categorical
17 | - title: Statistical operations
18 | pages:
19 | - error_bars
20 | - regression
21 | - title: Multi-plot grids
22 | pages:
23 | - axis_grids
24 | - title: Figure aesthetics
25 | pages:
26 | - aesthetics
27 | - color_palettes
28 |
--------------------------------------------------------------------------------
/doc/whatsnew/index.rst:
--------------------------------------------------------------------------------
1 | .. _whatsnew:
2 |
3 | What's new in each version
4 | ==========================
5 |
6 | v0.13
7 | -----
8 | .. toctree::
9 | :maxdepth: 2
10 |
11 | v0.13.2
12 | v0.13.1
13 | v0.13.0
14 |
15 | v0.12
16 | -----
17 | .. toctree::
18 | :maxdepth: 2
19 |
20 | v0.12.2
21 | v0.12.1
22 | v0.12.0
23 |
24 | v0.11
25 | -----
26 | .. toctree::
27 | :maxdepth: 2
28 |
29 | v0.11.2
30 | v0.11.1
31 | v0.11.0
32 |
33 | v0.10
34 | -----
35 | .. toctree::
36 | :maxdepth: 2
37 |
38 | v0.10.1
39 | v0.10.0
40 |
41 | v0.9
42 | ----
43 | .. toctree::
44 | :maxdepth: 2
45 |
46 | v0.9.1
47 | v0.9.0
48 |
49 | v0.8
50 | ----
51 | .. toctree::
52 | :maxdepth: 2
53 |
54 | v0.8.1
55 | v0.8.0
56 |
57 | v0.7
58 | ----
59 | .. toctree::
60 | :maxdepth: 2
61 |
62 | v0.7.1
63 | v0.7.0
64 |
65 | v0.6
66 | ----
67 | .. toctree::
68 | :maxdepth: 2
69 |
70 | v0.6.0
71 |
72 | v0.5
73 | ----
74 | .. toctree::
75 | :maxdepth: 2
76 |
77 | v0.5.1
78 | v0.5.0
79 |
80 | v0.4
81 | ----
82 | .. toctree::
83 | :maxdepth: 2
84 |
85 | v0.4.0
86 |
87 | v0.3
88 | ----
89 | .. toctree::
90 | :maxdepth: 2
91 |
92 | v0.3.1
93 | v0.3.0
94 |
95 | v0.2
96 | ----
97 | .. toctree::
98 | :maxdepth: 2
99 |
100 | v0.2.1
101 | v0.2.0
102 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.10.0.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.10.0 (January 2020)
3 | ----------------------
4 |
5 | This is a major update that is being released simultaneously with version 0.9.1. It has all of the same features (and bugs!) as 0.9.1, but there are important changes to the dependencies.
6 |
7 | Most notably, all support for Python 2 has now been dropped. Support for Python 3.5 has also been dropped. Seaborn is now strictly compatible with Python 3.6+.
8 |
9 | Minimally supported versions of the dependent PyData libraries have also been increased, in some cases substantially. While seaborn has tended to be very conservative about maintaining compatibility with older dependencies, this was causing increasing pain during development. At the same time, these libraries are now much easier to install. Going forward, seaborn will likely stay close to the `Numpy community guidelines `_ for version support.
10 |
11 | This release also removes a few previously-deprecated features:
12 |
13 | - The ``tsplot`` function and ``seaborn.timeseries`` module have been removed. Recall that ``tsplot`` was replaced with :func:`lineplot`.
14 |
15 | - The ``seaborn.apionly`` entry-point has been removed.
16 |
17 | - The ``seaborn.linearmodels`` module (previously renamed to ``seaborn.regression``) has been removed.
18 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.10.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.10.1 (April 2020)
3 | --------------------
4 |
5 | This is minor release with bug fixes for issues identified since 0.10.0.
6 |
7 | - Fixed a bug that appeared within the bootstrapping algorithm on 32-bit systems.
8 |
9 | - Fixed a bug where :func:`regplot` would crash on singleton inputs. Now a crash is avoided and regression estimation/plotting is skipped.
10 |
11 | - Fixed a bug where :func:`heatmap` would ignore user-specified under/over/bad values when recentering a colormap.
12 |
13 | - Fixed a bug where :func:`heatmap` would use values from masked cells when computing default colormap limits.
14 |
15 | - Fixed a bug where :func:`despine` would cause an error when trying to trim spines on a matplotlib categorical axis.
16 |
17 | - Adapted to a change in matplotlib that caused problems with single swarm plots.
18 |
19 | - Added the ``showfliers`` parameter to :func:`boxenplot` to suppress plotting of outlier data points, matching the API of :func:`boxplot`.
20 |
21 | - Avoided seeing an error from statmodels when data with an IQR of 0 is passed to :func:`kdeplot`.
22 |
23 | - Added the ``legend.title_fontsize`` to the :func:`plotting_context` definition.
24 |
25 | - Deprecated several utility functions that are no longer used internally (``percentiles``, ``sig_stars``, ``pmf_hist``, and ``sort_df``).
26 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.11.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.11.1 (December 2020)
3 | -----------------------
4 |
5 | This a bug fix release and is a recommended upgrade for all users on v0.11.0.
6 |
7 | - |Enhancement| Reduced the use of matplotlib global state in the :ref:`multi-grid classes ` (:pr:`2388`).
8 |
9 | - |Fix| Restored support for using tuples or numeric keys to reference fields in a long-form `data` object (:pr:`2386`).
10 |
11 | - |Fix| Fixed a bug in :func:`lineplot` where NAs were propagating into the confidence interval, sometimes erasing it from the plot (:pr:`2273`).
12 |
13 | - |Fix| Fixed a bug in :class:`PairGrid`/:func:`pairplot` where diagonal axes would be empty when the grid was not square and the diagonal axes did not contain the marginal plots (:pr:`2270`).
14 |
15 | - |Fix| Fixed a bug in :class:`PairGrid`/:func:`pairplot` where off-diagonal plots would not appear when column names in `data` had non-string type (:pr:`2368`).
16 |
17 | - |Fix| Fixed a bug where categorical dtype information was ignored when data consisted of boolean or boolean-like values (:pr:`2379`).
18 |
19 | - |Fix| Fixed a bug in :class:`FacetGrid` where interior tick labels would be hidden when only the orthogonal axis was shared (:pr:`2347`).
20 |
21 | - |Fix| Fixed a bug in :class:`FacetGrid` that caused an error when `legend_out=False` was set (:pr:`2304`).
22 |
23 | - |Fix| Fixed a bug in :func:`kdeplot` where ``common_norm=True`` was ignored if ``hue`` was not assigned (:pr:`2378`).
24 |
25 | - |Fix| Fixed a bug in :func:`displot` where the ``row_order`` and ``col_order`` parameters were not used (:pr:`2262`).
26 |
27 | - |Fix| Fixed a bug in :class:`PairGrid`/:func:`pairplot` that caused an exception when using `corner=True` and `diag_kind=None` (:pr:`2382`).
28 |
29 | - |Fix| Fixed a bug in :func:`clustermap` where `annot=False` was ignored (:pr:`2323`).
30 |
31 | - |Fix| Fixed a bug in :func:`clustermap` where row/col color annotations could not have a categorical dtype (:pr:`2389`).
32 |
33 | - |Fix| Fixed a bug in :func:`boxenplot` where the `linewidth` parameter was ignored (:pr:`2287`).
34 |
35 | - |Fix| Raise a more informative error in :class:`PairGrid`/:func:`pairplot` when no variables can be found to define the rows/columns of the grid (:pr:`2382`).
36 |
37 | - |Fix| Raise a more informative error from :func:`clustermap` if row/col color objects have semantic index but data object does not (:pr:`2313`).
38 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.12.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.12.1 (October 2022)
3 | ----------------------
4 |
5 | This is an incremental release that is a recommended upgrade for all users. It addresses a handful of bugs / regressions in v0.12.0 and adds several features and enhancements to the new :doc:`objects interface `.
6 |
7 | - |Feature| Added the :class:`objects.Text` mark (:pr:`3051`).
8 |
9 | - |Feature| Added the :class:`objects.Dash` mark (:pr:`3074`).
10 |
11 | - |Feature| Added the :class:`objects.Perc` stat (:pr:`3063`).
12 |
13 | - |Feature| Added the :class:`objects.Count` stat (:pr:`3086`).
14 |
15 | - |Feature| The :class:`objects.Band` and :class:`objects.Range` marks will now cover the full extent of the data if `min` / `max` variables are not explicitly assigned or added in a transform (:pr:`3056`).
16 |
17 | - |Enhancement| |Defaults| The :class:`objects.Jitter` move now applies a small amount of jitter by default (:pr:`3066`).
18 |
19 | - |Enhancement| |Defaults| Axes with a :class:`objects.Nominal` scale now appear like categorical axes in classic seaborn, with fixed margins, no grid, and an inverted y axis (:pr:`3069`).
20 |
21 | - |Enhancement| |API| The :meth:`objects.Continuous.label` method now accepts `base=None` to override the default formatter with a log transform (:pr:`3087`).
22 |
23 | - |Enhancement| |Fix| Marks that sort along the orient axis (e.g. :class:`objects.Line`) now use a stable algorithm (:pr:`3064`).
24 |
25 | - |Enhancement| |Fix| Added a `label` parameter to :func:`pointplot`, which addresses a regression in 0.12.0 when :func:`pointplot` is passed to :class:`FacetGrid` (:pr:`3016`).
26 |
27 | - |Fix| Fixed a bug that caused an exception when more than two layers with the same mappings were added to :class:`objects.Plot` (:pr:`3055`).
28 |
29 | - |Fix| Made :class:`objects.PolyFit` robust to missing data (:pr:`3010`).
30 |
31 | - |Fix| Fixed a bug in :class:`objects.Plot` that occurred when data assigned to the orient coordinate had zero variance (:pr:`3084`).
32 |
33 | - |Fix| Fixed a regression in :func:`kdeplot` where passing `cmap` for an unfilled bivariate plot would raise an exception (:pr:`3065`).
34 |
35 | - |Fix| Addressed a performance regression in :func:`lineplot` with a large number of unique x values (:pr:`3081`).
36 |
37 | - |Build| Seaborn no longer contains doctest-style examples, simplifying the testing infrastructure (:pr:`3034`).
38 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.12.2.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.12.2 (December 2022)
3 | -----------------------
4 |
5 | This is an incremental release that is a recommended upgrade for all users. It is very likely the final release of the 0.12 series and the last version to support Python 3.7.
6 |
7 | - |Feature| Added the :class:`objects.KDE` stat (:pr:`3111`).
8 |
9 | - |Feature| Added the :class:`objects.Boolean` scale (:pr:`3205`).
10 |
11 | - |Enhancement| Improved user feedback for failures during plot compilation by catching exceptions and re-raising with a `PlotSpecError` that provides additional context. (:pr:`3203`).
12 |
13 | - |Fix| Improved calculation of automatic mark widths with unshared facet axes (:pr:`3119`).
14 |
15 | - |Fix| Improved robustness to empty data in several components of the objects interface (:pr:`3202`).
16 |
17 | - |Fix| Fixed a bug where legends for numeric variables with large values would be incorrectly shown (i.e. with a missing offset or exponent; :pr:`3187`).
18 |
19 | - |Fix| Fixed a regression in v0.12.0 where manually-added labels could have duplicate legend entries (:pr:`3116`).
20 |
21 | - |Fix| Fixed a bug in :func:`histplot` with `kde=True` and `log_scale=True` where the curve was not scaled properly (:pr:`3173`).
22 |
23 | - |Fix| Fixed a bug in :func:`relplot` where inner axis labels would be shown when axis sharing was disabled (:pr:`3180`).
24 |
25 | - |Fix| Fixed a bug in :class:`objects.Continuous` to avoid an exception with boolean data (:pr:`3189`).
26 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.13.1.rst:
--------------------------------------------------------------------------------
1 | v0.13.1 (December 2023)
2 | -----------------------
3 |
4 | This is a minor release with some bug fixes and a couple new features. All users are encouraged to update.
5 |
6 | - |Feature| Added support for weighted mean estimation (with boostrap CIs) in :func:`lineplot`, :func:`barplot`, :func:`pointplot`, and :class:`objects.Est` (:pr:`3580`, :pr:`3586`).
7 |
8 | - |Feature| Added the `extent` option to :meth:`objects.Plot.layout` (:pr:`3552`).
9 |
10 | - |Fix| Fixed a regression in v0.13.0 that triggered an exception when working with non-numpy data types (:pr:`3516`).
11 |
12 | - |Fix| Fixed a bug in :class:`objects.Plot` so that tick labels are shown for wrapped axes that aren't in the bottom-most row (:pr:`3600`).
13 |
14 | - |Fix| Fixed a bug in :func:`catplot` where a blank legend would be added when `hue` was redundantly assigned (:pr:`3540`).
15 |
16 | - |Fix| Fixed a bug in :func:`catplot` where the `edgecolor` parameter was ignored with `kind="bar"` (:pr:`3547`).
17 |
18 | - |Fix| Fixed a bug in :func:`boxplot` where an exception was raised when using the matplotlib `bootstrap` option (:pr:`3562`).
19 |
20 | - |Fix| Fixed a bug in :func:`lineplot` where an exception was raised when `hue` was assigned with an empty dataframe (:pr:`3569`).
21 |
22 | - |Fix| Fixed a bug in multiple categorical plots that raised with `hue=None` and `dodge=True`; this is now has no effect (:pr:`3605`).
23 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.13.2.rst:
--------------------------------------------------------------------------------
1 | v0.13.2 (January 2024)
2 | ----------------------
3 |
4 | This is a minor release containing internal changes that adapt to upcoming deprecations in pandas. All users are encouraged to update.
5 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.2.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.2.1 (December 2013)
3 | ----------------------
4 |
5 | This is a bugfix release, with no new features.
6 |
7 | Bug fixes
8 | ~~~~~~~~~
9 |
10 | - Changed the mechanics of ``violinplot()`` and ``boxplot()`` when using a
11 | ``Series`` object as data and performing a ``groupby`` to assign data to
12 | bins to address a problem that arises in Pandas 0.13.
13 |
14 | - Additionally fixed the ``groupby`` code to work with all styles of group
15 | specification (specifically, using a dictionary or a function now works).
16 |
17 | - Fixed a bug where artifacts from the kde fitting could undershoot and create
18 | a plot where the density axis starts below 0.
19 |
20 | - Ensured that data used for kde fitting is double-typed to avoid a low-level
21 | statsmodels error.
22 |
23 | - Changed the implementation of the histogram bin-width reference rule to
24 | take a ceiling of the estimated number of bins.
25 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.3.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.3.1 (April 2014)
3 | -------------------
4 |
5 | This is a minor release from 0.3 with fixes for several bugs.
6 |
7 | Plotting functions
8 | ~~~~~~~~~~~~~~~~~~
9 |
10 | - The size of the points in :func:`pointplot` and ``factorplot`` are now scaled with the linewidth for better aesthetics across different plotting contexts.
11 |
12 | - The :func:`pointplot` glyphs for different levels of the hue variable are drawn at different z-orders so that they appear uniform.
13 |
14 | Bug Fixes
15 | ~~~~~~~~~
16 |
17 | - Fixed a bug in :class:`FacetGrid` (and thus affecting lmplot and factorplot) that appeared when ``col_wrap`` was used with a number of facets that did not evenly divide into the column width.
18 |
19 | - Fixed an issue where the support for kernel density estimates was sometimes computed incorrectly.
20 |
21 | - Fixed a problem where ``hue`` variable levels that were not strings were missing in :class:`FacetGrid` legends.
22 |
23 | - When passing a color palette list in a ``with`` statement, the entire palette is now used instead of the first six colors.
24 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.5.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.5.1 (November 2014)
3 | ----------------------
4 |
5 | This is a bugfix release that includes a workaround for an issue in matplotlib 1.4.2 and fixes for two bugs in functions that were new in 0.5.0.
6 |
7 | - Implemented a workaround for a bug in matplotlib 1.4.2 that prevented point markers from being drawn when the seaborn styles had been set. See this `github issue `_ for more information.
8 |
9 | - Fixed a bug in :func:`heatmap` where the mask was vertically reversed relative to the data.
10 |
11 | - Fixed a bug in :func:`clustermap` when using nested lists of side colors.
12 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.7.0.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.7.0 (January 2016)
3 | ---------------------
4 |
5 | This is a major release from 0.6. The main new feature is :func:`swarmplot` which implements the beeswarm approach for drawing categorical scatterplots. There are also some performance improvements, bug fixes, and updates for compatibility with new versions of dependencies.
6 |
7 | - Added the :func:`swarmplot` function, which draws beeswarm plots. These are categorical scatterplots, similar to those produced by :func:`stripplot`, but position of the points on the categorical axis is chosen to avoid overlapping points. See the :ref:`categorical plot tutorial ` for more information.
8 |
9 | - Changed some of the :func:`stripplot` defaults to be closer to :func:`swarmplot`. Points are now somewhat smaller, have no outlines, and are not split by default when using ``hue``. These settings remain customizable through function parameters.
10 |
11 | - Added an additional rule when determining category order in categorical plots. Now, when numeric variables are used in a categorical role, the default behavior is to sort the unique levels of the variable (i.e they will be in proper numerical order). This can still be overridden by the appropriate ``{*_}order`` parameter, and variables with a ``category`` datatype will still follow the category order even if the levels are strictly numerical.
12 |
13 | - Changed how :func:`stripplot` draws points when using ``hue`` nesting with ``split=False`` so that the different ``hue`` levels are not drawn strictly on top of each other.
14 |
15 | - Improve performance for large dendrograms in :func:`clustermap`.
16 |
17 | - Added ``font.size`` to the plotting context definition so that the default output from ``plt.text`` will be scaled appropriately.
18 |
19 | - Fixed a bug in :func:`clustermap` when ``fastcluster`` is not installed.
20 |
21 | - Fixed a bug in the zscore calculation in :func:`clustermap`.
22 |
23 | - Fixed a bug in :func:`distplot` where sometimes the default number of bins would not be an integer.
24 |
25 | - Fixed a bug in :func:`stripplot` where a legend item would not appear for a ``hue`` level if there were no observations in the first group of points.
26 |
27 | - Heatmap colorbars are now rasterized for better performance in vector plots.
28 |
29 | - Added workarounds for some matplotlib boxplot issues, such as strange colors of outlier points.
30 |
31 | - Added workarounds for an issue where violinplot edges would be missing or have random colors.
32 |
33 | - Added a workaround for an issue where only one :func:`heatmap` cell would be annotated on some matplotlib backends.
34 |
35 | - Fixed a bug on newer versions of matplotlib where a colormap would be erroneously applied to scatterplots with only three observations.
36 |
37 | - Updated seaborn for compatibility with matplotlib 1.5.
38 |
39 | - Added compatibility for various IPython (and Jupyter) versions in functions that use widgets.
40 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.7.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.7.1 (June 2016)
3 | -------------------
4 |
5 | - Added the ability to put "caps" on the error bars that are drawn by :func:`barplot` or :func:`pointplot` (and, by extension, ``factorplot``). Additionally, the line width of the error bars can now be controlled. These changes involve the new parameters ``capsize`` and ``errwidth``. See the `github pull request (#898) `_ for examples of usage.
6 |
7 | - Improved the row and column colors display in :func:`clustermap`. It is now possible to pass Pandas objects for these elements and, when possible, the semantic information in the Pandas objects will be used to add labels to the plot. When Pandas objects are used, the color data is matched against the main heatmap based on the index, not on position. This is more accurate, but it may lead to different results if current code assumed positional matching.
8 |
9 | - Improved the luminance calculation that determines the annotation color in :func:`heatmap`.
10 |
11 | - The ``annot`` parameter of :func:`heatmap` now accepts a rectangular dataset in addition to a boolean value. If a dataset is passed, its values will be used for the annotations, while the main dataset will be used for the heatmap cell colors.
12 |
13 | - Fixed a bug in :class:`FacetGrid` that appeared when using ``col_wrap`` with missing ``col`` levels.
14 |
15 | - Made it possible to pass a tick locator object to the :func:`heatmap` colorbar.
16 |
17 | - Made it possible to use different styles (e.g., step) for :class:`PairGrid` histograms when there are multiple hue levels.
18 |
19 | - Fixed a bug in scipy-based univariate kernel density bandwidth calculation.
20 |
21 | - The :func:`reset_orig` function (and, by extension, importing ``seaborn.apionly``) resets matplotlib rcParams to their values at the time seaborn itself was imported, which should work better with rcParams changed by the jupyter notebook backend.
22 |
23 | - Removed some objects from the top-level ``seaborn`` namespace.
24 |
25 | - Improved unicode compatibility in :class:`FacetGrid`.
26 |
--------------------------------------------------------------------------------
/doc/whatsnew/v0.8.1.rst:
--------------------------------------------------------------------------------
1 |
2 | v0.8.1 (September 2017)
3 | -----------------------
4 |
5 | - Added a warning in :class:`FacetGrid` when passing a categorical plot function without specifying ``order`` (or ``hue_order`` when ``hue`` is used), which is likely to produce a plot that is incorrect.
6 |
7 | - Improved compatibility between :class:`FacetGrid` or :class:`PairGrid` and interactive matplotlib backends so that the legend no longer remains inside the figure when using ``legend_out=True``.
8 |
9 | - Changed categorical plot functions with small plot elements to use :func:`dark_palette` instead of :func:`light_palette` when generating a sequential palette from a specified color.
10 |
11 | - Improved robustness of :func:`kdeplot` and :func:`distplot` to data with fewer than two observations.
12 |
13 | - Fixed a bug in :func:`clustermap` when using ``yticklabels=False``.
14 |
15 | - Fixed a bug in :func:`pointplot` where colors were wrong if exactly three points were being drawn.
16 |
17 | - Fixed a bug in :func:`pointplot` where legend entries for missing data appeared with empty markers.
18 |
19 | - Fixed a bug in :func:`clustermap` where an error was raised when annotating the main heatmap and showing category colors.
20 |
21 | - Fixed a bug in :func:`clustermap` where row labels were not being properly rotated when they overlapped.
22 |
23 | - Fixed a bug in :func:`kdeplot` where the maximum limit on the density axes was not being updated when multiple densities were drawn.
24 |
25 | - Improved compatibility with future versions of pandas.
26 |
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *_files/
3 |
--------------------------------------------------------------------------------
/examples/anscombes_quartet.py:
--------------------------------------------------------------------------------
1 | """
2 | Anscombe's quartet
3 | ==================
4 |
5 | _thumb: .4, .4
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="ticks")
9 |
10 | # Load the example dataset for Anscombe's quartet
11 | df = sns.load_dataset("anscombe")
12 |
13 | # Show the results of a linear regression within each dataset
14 | sns.lmplot(
15 | data=df, x="x", y="y", col="dataset", hue="dataset",
16 | col_wrap=2, palette="muted", ci=None,
17 | height=4, scatter_kws={"s": 50, "alpha": 1}
18 | )
19 |
--------------------------------------------------------------------------------
/examples/different_scatter_variables.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot with multiple semantics
3 | ===================================
4 |
5 | _thumb: .45, .5
6 |
7 | """
8 | import seaborn as sns
9 | import matplotlib.pyplot as plt
10 | sns.set_theme(style="whitegrid")
11 |
12 | # Load the example diamonds dataset
13 | diamonds = sns.load_dataset("diamonds")
14 |
15 | # Draw a scatter plot while assigning point colors and sizes to different
16 | # variables in the dataset
17 | f, ax = plt.subplots(figsize=(6.5, 6.5))
18 | sns.despine(f, left=True, bottom=True)
19 | clarity_ranking = ["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"]
20 | sns.scatterplot(x="carat", y="price",
21 | hue="clarity", size="depth",
22 | palette="ch:r=-.2,d=.3_r",
23 | hue_order=clarity_ranking,
24 | sizes=(1, 8), linewidth=0,
25 | data=diamonds, ax=ax)
26 |
--------------------------------------------------------------------------------
/examples/errorband_lineplots.py:
--------------------------------------------------------------------------------
1 | """
2 | Timeseries plot with error bands
3 | ================================
4 |
5 | _thumb: .48, .45
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="darkgrid")
10 |
11 | # Load an example dataset with long-form data
12 | fmri = sns.load_dataset("fmri")
13 |
14 | # Plot the responses for different events and regions
15 | sns.lineplot(x="timepoint", y="signal",
16 | hue="region", style="event",
17 | data=fmri)
18 |
--------------------------------------------------------------------------------
/examples/faceted_histogram.py:
--------------------------------------------------------------------------------
1 | """
2 | Facetting histograms by subsets of data
3 | =======================================
4 |
5 | _thumb: .33, .57
6 | """
7 | import seaborn as sns
8 |
9 | sns.set_theme(style="darkgrid")
10 | df = sns.load_dataset("penguins")
11 | sns.displot(
12 | df, x="flipper_length_mm", col="species", row="sex",
13 | binwidth=3, height=3, facet_kws=dict(margin_titles=True),
14 | )
15 |
--------------------------------------------------------------------------------
/examples/faceted_lineplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Line plots on multiple facets
3 | =============================
4 |
5 | _thumb: .48, .42
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="ticks")
10 |
11 | dots = sns.load_dataset("dots")
12 |
13 | # Define the palette as a list to specify exact values
14 | palette = sns.color_palette("rocket_r")
15 |
16 | # Plot the lines on two facets
17 | sns.relplot(
18 | data=dots,
19 | x="time", y="firing_rate",
20 | hue="coherence", size="choice", col="align",
21 | kind="line", size_order=["T1", "T2"], palette=palette,
22 | height=5, aspect=.75, facet_kws=dict(sharex=False),
23 | )
24 |
--------------------------------------------------------------------------------
/examples/grouped_barplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Grouped barplots
3 | ================
4 |
5 | _thumb: .36, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="whitegrid")
9 |
10 | penguins = sns.load_dataset("penguins")
11 |
12 | # Draw a nested barplot by species and sex
13 | g = sns.catplot(
14 | data=penguins, kind="bar",
15 | x="species", y="body_mass_g", hue="sex",
16 | errorbar="sd", palette="dark", alpha=.6, height=6
17 | )
18 | g.despine(left=True)
19 | g.set_axis_labels("", "Body mass (g)")
20 | g.legend.set_title("")
21 |
--------------------------------------------------------------------------------
/examples/grouped_boxplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Grouped boxplots
3 | ================
4 |
5 | _thumb: .66, .45
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="ticks", palette="pastel")
10 |
11 | # Load the example tips dataset
12 | tips = sns.load_dataset("tips")
13 |
14 | # Draw a nested boxplot to show bills by day and time
15 | sns.boxplot(x="day", y="total_bill",
16 | hue="smoker", palette=["m", "g"],
17 | data=tips)
18 | sns.despine(offset=10, trim=True)
19 |
--------------------------------------------------------------------------------
/examples/grouped_violinplots.py:
--------------------------------------------------------------------------------
1 | """
2 | Grouped violinplots with split violins
3 | ======================================
4 |
5 | _thumb: .44, .47
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="dark")
9 |
10 | # Load the example tips dataset
11 | tips = sns.load_dataset("tips")
12 |
13 | # Draw a nested violinplot and split the violins for easier comparison
14 | sns.violinplot(data=tips, x="day", y="total_bill", hue="smoker",
15 | split=True, inner="quart", fill=False,
16 | palette={"Yes": "g", "No": ".35"})
17 |
--------------------------------------------------------------------------------
/examples/heat_scatter.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot heatmap
3 | -------------------
4 |
5 | _thumb: .5, .5
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="whitegrid")
10 |
11 | # Load the brain networks dataset, select subset, and collapse the multi-index
12 | df = sns.load_dataset("brain_networks", header=[0, 1, 2], index_col=0)
13 |
14 | used_networks = [1, 5, 6, 7, 8, 12, 13, 17]
15 | used_columns = (df.columns
16 | .get_level_values("network")
17 | .astype(int)
18 | .isin(used_networks))
19 | df = df.loc[:, used_columns]
20 |
21 | df.columns = df.columns.map("-".join)
22 |
23 | # Compute a correlation matrix and convert to long-form
24 | corr_mat = df.corr().stack().reset_index(name="correlation")
25 |
26 | # Draw each cell as a scatter point with varying size and color
27 | g = sns.relplot(
28 | data=corr_mat,
29 | x="level_0", y="level_1", hue="correlation", size="correlation",
30 | palette="vlag", hue_norm=(-1, 1), edgecolor=".7",
31 | height=10, sizes=(50, 250), size_norm=(-.2, .8),
32 | )
33 |
34 | # Tweak the figure to finalize
35 | g.set(xlabel="", ylabel="", aspect="equal")
36 | g.despine(left=True, bottom=True)
37 | g.ax.margins(.02)
38 | for label in g.ax.get_xticklabels():
39 | label.set_rotation(90)
40 |
--------------------------------------------------------------------------------
/examples/hexbin_marginals.py:
--------------------------------------------------------------------------------
1 | """
2 | Hexbin plot with marginal distributions
3 | =======================================
4 |
5 | _thumb: .45, .4
6 | """
7 | import numpy as np
8 | import seaborn as sns
9 | sns.set_theme(style="ticks")
10 |
11 | rs = np.random.RandomState(11)
12 | x = rs.gamma(2, size=1000)
13 | y = -.5 * x + rs.normal(size=1000)
14 |
15 | sns.jointplot(x=x, y=y, kind="hex", color="#4CB391")
16 |
--------------------------------------------------------------------------------
/examples/histogram_stacked.py:
--------------------------------------------------------------------------------
1 | """
2 | Stacked histogram on a log scale
3 | ================================
4 |
5 | _thumb: .5, .45
6 |
7 | """
8 | import seaborn as sns
9 | import matplotlib as mpl
10 | import matplotlib.pyplot as plt
11 |
12 | sns.set_theme(style="ticks")
13 |
14 | diamonds = sns.load_dataset("diamonds")
15 |
16 | f, ax = plt.subplots(figsize=(7, 5))
17 | sns.despine(f)
18 |
19 | sns.histplot(
20 | diamonds,
21 | x="price", hue="cut",
22 | multiple="stack",
23 | palette="light:m_r",
24 | edgecolor=".3",
25 | linewidth=.5,
26 | log_scale=True,
27 | )
28 | ax.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
29 | ax.set_xticks([500, 1000, 2000, 5000, 10000])
30 |
--------------------------------------------------------------------------------
/examples/horizontal_boxplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Horizontal boxplot with observations
3 | ====================================
4 |
5 | _thumb: .7, .37
6 | """
7 | import seaborn as sns
8 | import matplotlib.pyplot as plt
9 |
10 | sns.set_theme(style="ticks")
11 |
12 | # Initialize the figure with a logarithmic x axis
13 | f, ax = plt.subplots(figsize=(7, 6))
14 | ax.set_xscale("log")
15 |
16 | # Load the example planets dataset
17 | planets = sns.load_dataset("planets")
18 |
19 | # Plot the orbital period with horizontal boxes
20 | sns.boxplot(
21 | planets, x="distance", y="method", hue="method",
22 | whis=[0, 100], width=.6, palette="vlag"
23 | )
24 |
25 | # Add in points to show each observation
26 | sns.stripplot(planets, x="distance", y="method", size=4, color=".3")
27 |
28 | # Tweak the visual presentation
29 | ax.xaxis.grid(True)
30 | ax.set(ylabel="")
31 | sns.despine(trim=True, left=True)
32 |
--------------------------------------------------------------------------------
/examples/jitter_stripplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Conditional means with observations
3 | ===================================
4 |
5 | """
6 | import seaborn as sns
7 | import matplotlib.pyplot as plt
8 |
9 | sns.set_theme(style="whitegrid")
10 | iris = sns.load_dataset("iris")
11 |
12 | # "Melt" the dataset to "long-form" or "tidy" representation
13 | iris = iris.melt(id_vars="species", var_name="measurement")
14 |
15 | # Initialize the figure
16 | f, ax = plt.subplots()
17 | sns.despine(bottom=True, left=True)
18 |
19 | # Show each observation with a scatterplot
20 | sns.stripplot(
21 | data=iris, x="value", y="measurement", hue="species",
22 | dodge=True, alpha=.25, zorder=1, legend=False,
23 | )
24 |
25 | # Show the conditional means, aligning each pointplot in the
26 | # center of the strips by adjusting the width allotted to each
27 | # category (.8 by default) by the number of hue levels
28 | sns.pointplot(
29 | data=iris, x="value", y="measurement", hue="species",
30 | dodge=.8 - .8 / 3, palette="dark", errorbar=None,
31 | markers="d", markersize=4, linestyle="none",
32 | )
33 |
34 | # Improve the legend
35 | sns.move_legend(
36 | ax, loc="lower right", ncol=3, frameon=True, columnspacing=1, handletextpad=0,
37 | )
38 |
--------------------------------------------------------------------------------
/examples/joint_histogram.py:
--------------------------------------------------------------------------------
1 | """
2 | Joint and marginal histograms
3 | =============================
4 |
5 | _thumb: .52, .505
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="ticks")
10 |
11 | # Load the planets dataset and initialize the figure
12 | planets = sns.load_dataset("planets")
13 | g = sns.JointGrid(data=planets, x="year", y="distance", marginal_ticks=True)
14 |
15 | # Set a log scaling on the y axis
16 | g.ax_joint.set(yscale="log")
17 |
18 | # Create an inset legend for the histogram colorbar
19 | cax = g.figure.add_axes([.15, .55, .02, .2])
20 |
21 | # Add the joint and marginal histogram plots
22 | g.plot_joint(
23 | sns.histplot, discrete=(True, False),
24 | cmap="light:#03012d", pmax=.8, cbar=True, cbar_ax=cax
25 | )
26 | g.plot_marginals(sns.histplot, element="step", color="#03012d")
27 |
--------------------------------------------------------------------------------
/examples/joint_kde.py:
--------------------------------------------------------------------------------
1 | """
2 | Joint kernel density estimate
3 | =============================
4 |
5 | _thumb: .6, .4
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="ticks")
9 |
10 | # Load the penguins dataset
11 | penguins = sns.load_dataset("penguins")
12 |
13 | # Show the joint distribution using kernel density estimation
14 | g = sns.jointplot(
15 | data=penguins,
16 | x="bill_length_mm", y="bill_depth_mm", hue="species",
17 | kind="kde",
18 | )
19 |
--------------------------------------------------------------------------------
/examples/kde_ridgeplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Overlapping densities ('ridge plot')
3 | ====================================
4 |
5 |
6 | """
7 | import numpy as np
8 | import pandas as pd
9 | import seaborn as sns
10 | import matplotlib.pyplot as plt
11 | sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
12 |
13 | # Create the data
14 | rs = np.random.RandomState(1979)
15 | x = rs.randn(500)
16 | g = np.tile(list("ABCDEFGHIJ"), 50)
17 | df = pd.DataFrame(dict(x=x, g=g))
18 | m = df.g.map(ord)
19 | df["x"] += m
20 |
21 | # Initialize the FacetGrid object
22 | pal = sns.cubehelix_palette(10, rot=-.25, light=.7)
23 | g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal)
24 |
25 | # Draw the densities in a few steps
26 | g.map(sns.kdeplot, "x",
27 | bw_adjust=.5, clip_on=False,
28 | fill=True, alpha=1, linewidth=1.5)
29 | g.map(sns.kdeplot, "x", clip_on=False, color="w", lw=2, bw_adjust=.5)
30 |
31 | # passing color=None to refline() uses the hue mapping
32 | g.refline(y=0, linewidth=2, linestyle="-", color=None, clip_on=False)
33 |
34 |
35 | # Define and use a simple function to label the plot in axes coordinates
36 | def label(x, color, label):
37 | ax = plt.gca()
38 | ax.text(0, .2, label, fontweight="bold", color=color,
39 | ha="left", va="center", transform=ax.transAxes)
40 |
41 |
42 | g.map(label, "x")
43 |
44 | # Set the subplots to overlap
45 | g.figure.subplots_adjust(hspace=-.25)
46 |
47 | # Remove axes details that don't play well with overlap
48 | g.set_titles("")
49 | g.set(yticks=[], ylabel="")
50 | g.despine(bottom=True, left=True)
51 |
--------------------------------------------------------------------------------
/examples/large_distributions.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting large distributions
3 | ============================
4 |
5 | """
6 | import seaborn as sns
7 | sns.set_theme(style="whitegrid")
8 |
9 | diamonds = sns.load_dataset("diamonds")
10 | clarity_ranking = ["I1", "SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"]
11 |
12 | sns.boxenplot(
13 | diamonds, x="clarity", y="carat",
14 | color="b", order=clarity_ranking, width_method="linear",
15 | )
16 |
--------------------------------------------------------------------------------
/examples/layered_bivariate_plot.py:
--------------------------------------------------------------------------------
1 | """
2 | Bivariate plot with multiple elements
3 | =====================================
4 |
5 |
6 | """
7 | import numpy as np
8 | import seaborn as sns
9 | import matplotlib.pyplot as plt
10 | sns.set_theme(style="dark")
11 |
12 | # Simulate data from a bivariate Gaussian
13 | n = 10000
14 | mean = [0, 0]
15 | cov = [(2, .4), (.4, .2)]
16 | rng = np.random.RandomState(0)
17 | x, y = rng.multivariate_normal(mean, cov, n).T
18 |
19 | # Draw a combo histogram and scatterplot with density contours
20 | f, ax = plt.subplots(figsize=(6, 6))
21 | sns.scatterplot(x=x, y=y, s=5, color=".15")
22 | sns.histplot(x=x, y=y, bins=50, pthresh=.1, cmap="mako")
23 | sns.kdeplot(x=x, y=y, levels=5, color="w", linewidths=1)
24 |
--------------------------------------------------------------------------------
/examples/logistic_regression.py:
--------------------------------------------------------------------------------
1 | """
2 | Faceted logistic regression
3 | ===========================
4 |
5 | _thumb: .58, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="darkgrid")
9 |
10 | # Load the example Titanic dataset
11 | df = sns.load_dataset("titanic")
12 |
13 | # Make a custom palette with gendered colors
14 | pal = dict(male="#6495ED", female="#F08080")
15 |
16 | # Show the survival probability as a function of age and sex
17 | g = sns.lmplot(x="age", y="survived", col="sex", hue="sex", data=df,
18 | palette=pal, y_jitter=.02, logistic=True, truncate=False)
19 | g.set(xlim=(0, 80), ylim=(-.05, 1.05))
20 |
--------------------------------------------------------------------------------
/examples/many_facets.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting on a large number of facets
3 | ====================================
4 |
5 | _thumb: .4, .3
6 |
7 | """
8 | import numpy as np
9 | import pandas as pd
10 | import seaborn as sns
11 | import matplotlib.pyplot as plt
12 |
13 | sns.set_theme(style="ticks")
14 |
15 | # Create a dataset with many short random walks
16 | rs = np.random.RandomState(4)
17 | pos = rs.randint(-1, 2, (20, 5)).cumsum(axis=1)
18 | pos -= pos[:, 0, np.newaxis]
19 | step = np.tile(range(5), 20)
20 | walk = np.repeat(range(20), 5)
21 | df = pd.DataFrame(np.c_[pos.flat, step, walk],
22 | columns=["position", "step", "walk"])
23 |
24 | # Initialize a grid of plots with an Axes for each walk
25 | grid = sns.FacetGrid(df, col="walk", hue="walk", palette="tab20c",
26 | col_wrap=4, height=1.5)
27 |
28 | # Draw a horizontal line to show the starting point
29 | grid.refline(y=0, linestyle=":")
30 |
31 | # Draw a line plot to show the trajectory of each random walk
32 | grid.map(plt.plot, "step", "position", marker="o")
33 |
34 | # Adjust the tick positions and labels
35 | grid.set(xticks=np.arange(5), yticks=[-3, 3],
36 | xlim=(-.5, 4.5), ylim=(-3.5, 3.5))
37 |
38 | # Adjust the arrangement of the plots
39 | grid.fig.tight_layout(w_pad=1)
40 |
--------------------------------------------------------------------------------
/examples/many_pairwise_correlations.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting a diagonal correlation matrix
3 | ======================================
4 |
5 | _thumb: .3, .6
6 | """
7 | from string import ascii_letters
8 | import numpy as np
9 | import pandas as pd
10 | import seaborn as sns
11 | import matplotlib.pyplot as plt
12 |
13 | sns.set_theme(style="white")
14 |
15 | # Generate a large random dataset
16 | rs = np.random.RandomState(33)
17 | d = pd.DataFrame(data=rs.normal(size=(100, 26)),
18 | columns=list(ascii_letters[26:]))
19 |
20 | # Compute the correlation matrix
21 | corr = d.corr()
22 |
23 | # Generate a mask for the upper triangle
24 | mask = np.triu(np.ones_like(corr, dtype=bool))
25 |
26 | # Set up the matplotlib figure
27 | f, ax = plt.subplots(figsize=(11, 9))
28 |
29 | # Generate a custom diverging colormap
30 | cmap = sns.diverging_palette(230, 20, as_cmap=True)
31 |
32 | # Draw the heatmap with the mask and correct aspect ratio
33 | sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
34 | square=True, linewidths=.5, cbar_kws={"shrink": .5})
35 |
--------------------------------------------------------------------------------
/examples/marginal_ticks.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot with marginal ticks
3 | ===============================
4 |
5 | _thumb: .66, .34
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="white", color_codes=True)
9 | mpg = sns.load_dataset("mpg")
10 |
11 | # Use JointGrid directly to draw a custom plot
12 | g = sns.JointGrid(data=mpg, x="mpg", y="acceleration", space=0, ratio=17)
13 | g.plot_joint(sns.scatterplot, size=mpg["horsepower"], sizes=(30, 120),
14 | color="g", alpha=.6, legend=False)
15 | g.plot_marginals(sns.rugplot, height=1, color="g", alpha=.6)
16 |
--------------------------------------------------------------------------------
/examples/multiple_bivariate_kde.py:
--------------------------------------------------------------------------------
1 | """
2 | Multiple bivariate KDE plots
3 | ============================
4 |
5 | _thumb: .6, .45
6 | """
7 | import seaborn as sns
8 | import matplotlib.pyplot as plt
9 |
10 | sns.set_theme(style="darkgrid")
11 | iris = sns.load_dataset("iris")
12 |
13 | # Set up the figure
14 | f, ax = plt.subplots(figsize=(8, 8))
15 | ax.set_aspect("equal")
16 |
17 | # Draw a contour plot to represent each bivariate density
18 | sns.kdeplot(
19 | data=iris.query("species != 'versicolor'"),
20 | x="sepal_width",
21 | y="sepal_length",
22 | hue="species",
23 | thresh=.1,
24 | )
25 |
--------------------------------------------------------------------------------
/examples/multiple_conditional_kde.py:
--------------------------------------------------------------------------------
1 | """
2 | Conditional kernel density estimate
3 | ===================================
4 |
5 | _thumb: .4, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="whitegrid")
9 |
10 | # Load the diamonds dataset
11 | diamonds = sns.load_dataset("diamonds")
12 |
13 | # Plot the distribution of clarity ratings, conditional on carat
14 | sns.displot(
15 | data=diamonds,
16 | x="carat", hue="cut",
17 | kind="kde", height=6,
18 | multiple="fill", clip=(0, None),
19 | palette="ch:rot=-.25,hue=1,light=.75",
20 | )
21 |
--------------------------------------------------------------------------------
/examples/multiple_ecdf.py:
--------------------------------------------------------------------------------
1 | """
2 | Facetted ECDF plots
3 | ===================
4 |
5 | _thumb: .30, .49
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="ticks")
9 | mpg = sns.load_dataset("mpg")
10 |
11 | colors = (250, 70, 50), (350, 70, 50)
12 | cmap = sns.blend_palette(colors, input="husl", as_cmap=True)
13 | sns.displot(
14 | mpg,
15 | x="displacement", col="origin", hue="model_year",
16 | kind="ecdf", aspect=.75, linewidth=2, palette=cmap,
17 | )
18 |
--------------------------------------------------------------------------------
/examples/multiple_regression.py:
--------------------------------------------------------------------------------
1 | """
2 | Multiple linear regression
3 | ==========================
4 |
5 | _thumb: .45, .45
6 | """
7 | import seaborn as sns
8 | sns.set_theme()
9 |
10 | # Load the penguins dataset
11 | penguins = sns.load_dataset("penguins")
12 |
13 | # Plot sepal width as a function of sepal_length across days
14 | g = sns.lmplot(
15 | data=penguins,
16 | x="bill_length_mm", y="bill_depth_mm", hue="species",
17 | height=5
18 | )
19 |
20 | # Use more informative axis labels than are provided by default
21 | g.set_axis_labels("Snoot length (mm)", "Snoot depth (mm)")
22 |
--------------------------------------------------------------------------------
/examples/pair_grid_with_kde.py:
--------------------------------------------------------------------------------
1 | """
2 | Paired density and scatterplot matrix
3 | =====================================
4 |
5 | _thumb: .5, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="white")
9 |
10 | df = sns.load_dataset("penguins")
11 |
12 | g = sns.PairGrid(df, diag_sharey=False)
13 | g.map_upper(sns.scatterplot, s=15)
14 | g.map_lower(sns.kdeplot)
15 | g.map_diag(sns.kdeplot, lw=2)
16 |
--------------------------------------------------------------------------------
/examples/paired_pointplots.py:
--------------------------------------------------------------------------------
1 | """
2 | Paired categorical plots
3 | ========================
4 |
5 | """
6 | import seaborn as sns
7 | sns.set_theme(style="whitegrid")
8 |
9 | # Load the example Titanic dataset
10 | titanic = sns.load_dataset("titanic")
11 |
12 | # Set up a grid to plot survival probability against several variables
13 | g = sns.PairGrid(titanic, y_vars="survived",
14 | x_vars=["class", "sex", "who", "alone"],
15 | height=5, aspect=.5)
16 |
17 | # Draw a seaborn pointplot onto each Axes
18 | g.map(sns.pointplot, color="xkcd:plum")
19 | g.set(ylim=(0, 1))
20 | sns.despine(fig=g.fig, left=True)
21 |
--------------------------------------------------------------------------------
/examples/pairgrid_dotplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Dot plot with several variables
3 | ===============================
4 |
5 | _thumb: .3, .3
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="whitegrid")
9 |
10 | # Load the dataset
11 | crashes = sns.load_dataset("car_crashes")
12 |
13 | # Make the PairGrid
14 | g = sns.PairGrid(crashes.sort_values("total", ascending=False),
15 | x_vars=crashes.columns[:-3], y_vars=["abbrev"],
16 | height=10, aspect=.25)
17 |
18 | # Draw a dot plot using the stripplot function
19 | g.map(sns.stripplot, size=10, orient="h", jitter=False,
20 | palette="flare_r", linewidth=1, edgecolor="w")
21 |
22 | # Use the same x axis limits on all columns and add better labels
23 | g.set(xlim=(0, 25), xlabel="Crashes", ylabel="")
24 |
25 | # Use semantically meaningful titles for the columns
26 | titles = ["Total crashes", "Speeding crashes", "Alcohol crashes",
27 | "Not distracted crashes", "No previous crashes"]
28 |
29 | for ax, title in zip(g.axes.flat, titles):
30 |
31 | # Set a different title for each axes
32 | ax.set(title=title)
33 |
34 | # Make the grid horizontal instead of vertical
35 | ax.xaxis.grid(False)
36 | ax.yaxis.grid(True)
37 |
38 | sns.despine(left=True, bottom=True)
39 |
--------------------------------------------------------------------------------
/examples/palette_choices.py:
--------------------------------------------------------------------------------
1 | """
2 | Color palette choices
3 | =====================
4 |
5 | """
6 | import numpy as np
7 | import seaborn as sns
8 | import matplotlib.pyplot as plt
9 | sns.set_theme(style="white", context="talk")
10 | rs = np.random.RandomState(8)
11 |
12 | # Set up the matplotlib figure
13 | f, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(7, 5), sharex=True)
14 |
15 | # Generate some sequential data
16 | x = np.array(list("ABCDEFGHIJ"))
17 | y1 = np.arange(1, 11)
18 | sns.barplot(x=x, y=y1, hue=x, palette="rocket", ax=ax1)
19 | ax1.axhline(0, color="k", clip_on=False)
20 | ax1.set_ylabel("Sequential")
21 |
22 | # Center the data to make it diverging
23 | y2 = y1 - 5.5
24 | sns.barplot(x=x, y=y2, hue=x, palette="vlag", ax=ax2)
25 | ax2.axhline(0, color="k", clip_on=False)
26 | ax2.set_ylabel("Diverging")
27 |
28 | # Randomly reorder the data to make it qualitative
29 | y3 = rs.choice(y1, len(y1), replace=False)
30 | sns.barplot(x=x, y=y3, hue=x, palette="deep", ax=ax3)
31 | ax3.axhline(0, color="k", clip_on=False)
32 | ax3.set_ylabel("Qualitative")
33 |
34 | # Finalize the plot
35 | sns.despine(bottom=True)
36 | plt.setp(f.axes, yticks=[])
37 | plt.tight_layout(h_pad=2)
38 |
--------------------------------------------------------------------------------
/examples/palette_generation.py:
--------------------------------------------------------------------------------
1 | """
2 | Different cubehelix palettes
3 | ============================
4 |
5 | _thumb: .4, .65
6 | """
7 | import numpy as np
8 | import seaborn as sns
9 | import matplotlib.pyplot as plt
10 |
11 | sns.set_theme(style="white")
12 | rs = np.random.RandomState(50)
13 |
14 | # Set up the matplotlib figure
15 | f, axes = plt.subplots(3, 3, figsize=(9, 9), sharex=True, sharey=True)
16 |
17 | # Rotate the starting point around the cubehelix hue circle
18 | for ax, s in zip(axes.flat, np.linspace(0, 3, 10)):
19 |
20 | # Create a cubehelix colormap to use with kdeplot
21 | cmap = sns.cubehelix_palette(start=s, light=1, as_cmap=True)
22 |
23 | # Generate and plot a random bivariate dataset
24 | x, y = rs.normal(size=(2, 50))
25 | sns.kdeplot(
26 | x=x, y=y,
27 | cmap=cmap, fill=True,
28 | clip=(-5, 5), cut=10,
29 | thresh=0, levels=15,
30 | ax=ax,
31 | )
32 | ax.set_axis_off()
33 |
34 | ax.set(xlim=(-3.5, 3.5), ylim=(-3.5, 3.5))
35 | f.subplots_adjust(0, 0, 1, 1, .08, .08)
36 |
--------------------------------------------------------------------------------
/examples/part_whole_bars.py:
--------------------------------------------------------------------------------
1 | """
2 | Horizontal bar plots
3 | ====================
4 |
5 | """
6 | import seaborn as sns
7 | import matplotlib.pyplot as plt
8 | sns.set_theme(style="whitegrid")
9 |
10 | # Initialize the matplotlib figure
11 | f, ax = plt.subplots(figsize=(6, 15))
12 |
13 | # Load the example car crash dataset
14 | crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
15 |
16 | # Plot the total crashes
17 | sns.set_color_codes("pastel")
18 | sns.barplot(x="total", y="abbrev", data=crashes,
19 | label="Total", color="b")
20 |
21 | # Plot the crashes where alcohol was involved
22 | sns.set_color_codes("muted")
23 | sns.barplot(x="alcohol", y="abbrev", data=crashes,
24 | label="Alcohol-involved", color="b")
25 |
26 | # Add a legend and informative axis label
27 | ax.legend(ncol=2, loc="lower right", frameon=True)
28 | ax.set(xlim=(0, 24), ylabel="",
29 | xlabel="Automobile collisions per billion miles")
30 | sns.despine(left=True, bottom=True)
31 |
--------------------------------------------------------------------------------
/examples/pointplot_anova.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting a three-way ANOVA
3 | ==========================
4 |
5 | _thumb: .42, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="whitegrid")
9 |
10 | # Load the example exercise dataset
11 | exercise = sns.load_dataset("exercise")
12 |
13 | # Draw a pointplot to show pulse as a function of three categorical factors
14 | g = sns.catplot(
15 | data=exercise, x="time", y="pulse", hue="kind", col="diet",
16 | capsize=.2, palette="YlGnBu_d", errorbar="se",
17 | kind="point", height=6, aspect=.75,
18 | )
19 | g.despine(left=True)
20 |
--------------------------------------------------------------------------------
/examples/radial_facets.py:
--------------------------------------------------------------------------------
1 | """
2 | FacetGrid with custom projection
3 | ================================
4 |
5 | _thumb: .33, .5
6 |
7 | """
8 | import numpy as np
9 | import pandas as pd
10 | import seaborn as sns
11 |
12 | sns.set_theme()
13 |
14 | # Generate an example radial datast
15 | r = np.linspace(0, 10, num=100)
16 | df = pd.DataFrame({'r': r, 'slow': r, 'medium': 2 * r, 'fast': 4 * r})
17 |
18 | # Convert the dataframe to long-form or "tidy" format
19 | df = pd.melt(df, id_vars=['r'], var_name='speed', value_name='theta')
20 |
21 | # Set up a grid of axes with a polar projection
22 | g = sns.FacetGrid(df, col="speed", hue="speed",
23 | subplot_kws=dict(projection='polar'), height=4.5,
24 | sharex=False, sharey=False, despine=False)
25 |
26 | # Draw a scatterplot onto each axes in the grid
27 | g.map(sns.scatterplot, "theta", "r")
28 |
--------------------------------------------------------------------------------
/examples/regression_marginals.py:
--------------------------------------------------------------------------------
1 | """
2 | Linear regression with marginal distributions
3 | =============================================
4 |
5 | _thumb: .65, .65
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="darkgrid")
9 |
10 | tips = sns.load_dataset("tips")
11 | g = sns.jointplot(x="total_bill", y="tip", data=tips,
12 | kind="reg", truncate=False,
13 | xlim=(0, 60), ylim=(0, 12),
14 | color="m", height=7)
15 |
--------------------------------------------------------------------------------
/examples/residplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting model residuals
3 | ========================
4 |
5 | """
6 | import numpy as np
7 | import seaborn as sns
8 | sns.set_theme(style="whitegrid")
9 |
10 | # Make an example dataset with y ~ x
11 | rs = np.random.RandomState(7)
12 | x = rs.normal(2, 1, 75)
13 | y = 2 + 1.5 * x + rs.normal(0, 2, 75)
14 |
15 | # Plot the residuals after fitting a linear model
16 | sns.residplot(x=x, y=y, lowess=True, color="g")
17 |
--------------------------------------------------------------------------------
/examples/scatter_bubbles.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot with varying point sizes and hues
3 | ==============================================
4 |
5 | _thumb: .45, .5
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="white")
10 |
11 | # Load the example mpg dataset
12 | mpg = sns.load_dataset("mpg")
13 |
14 | # Plot miles per gallon against horsepower with other semantics
15 | sns.relplot(x="horsepower", y="mpg", hue="origin", size="weight",
16 | sizes=(40, 400), alpha=.5, palette="muted",
17 | height=6, data=mpg)
18 |
--------------------------------------------------------------------------------
/examples/scatterplot_categorical.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot with categorical variables
3 | ======================================
4 |
5 | _thumb: .45, .45
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="whitegrid", palette="muted")
10 |
11 | # Load the penguins dataset
12 | df = sns.load_dataset("penguins")
13 |
14 | # Draw a categorical scatterplot to show each observation
15 | ax = sns.swarmplot(data=df, x="body_mass_g", y="sex", hue="species")
16 | ax.set(ylabel="")
17 |
--------------------------------------------------------------------------------
/examples/scatterplot_matrix.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot Matrix
3 | ==================
4 |
5 | _thumb: .3, .2
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="ticks")
9 |
10 | df = sns.load_dataset("penguins")
11 | sns.pairplot(df, hue="species")
12 |
--------------------------------------------------------------------------------
/examples/scatterplot_sizes.py:
--------------------------------------------------------------------------------
1 | """
2 | Scatterplot with continuous hues and sizes
3 | ==========================================
4 |
5 | _thumb: .51, .44
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="whitegrid")
10 |
11 | # Load the example planets dataset
12 | planets = sns.load_dataset("planets")
13 |
14 | cmap = sns.cubehelix_palette(rot=-.2, as_cmap=True)
15 | g = sns.relplot(
16 | data=planets,
17 | x="distance", y="orbital_period",
18 | hue="year", size="mass",
19 | palette=cmap, sizes=(10, 200),
20 | )
21 | g.set(xscale="log", yscale="log")
22 | g.ax.xaxis.grid(True, "minor", linewidth=.25)
23 | g.ax.yaxis.grid(True, "minor", linewidth=.25)
24 | g.despine(left=True, bottom=True)
25 |
--------------------------------------------------------------------------------
/examples/simple_violinplots.py:
--------------------------------------------------------------------------------
1 | """
2 | Horizontal, unfilled violinplots
3 | ================================
4 |
5 | _thumb: .5, .45
6 | """
7 | import seaborn as sns
8 |
9 | sns.set_theme()
10 |
11 | seaice = sns.load_dataset("seaice")
12 | seaice["Decade"] = seaice["Date"].dt.year.round(-1)
13 | sns.violinplot(seaice, x="Extent", y="Decade", orient="y", fill=False)
14 |
--------------------------------------------------------------------------------
/examples/smooth_bivariate_kde.py:
--------------------------------------------------------------------------------
1 | """
2 | Smooth kernel density with marginal histograms
3 | ==============================================
4 |
5 | _thumb: .48, .41
6 | """
7 | import seaborn as sns
8 | sns.set_theme(style="white")
9 |
10 | df = sns.load_dataset("penguins")
11 |
12 | g = sns.JointGrid(data=df, x="body_mass_g", y="bill_depth_mm", space=0)
13 | g.plot_joint(sns.kdeplot,
14 | fill=True, clip=((2200, 6800), (10, 25)),
15 | thresh=0, levels=100, cmap="rocket")
16 | g.plot_marginals(sns.histplot, color="#03051A", alpha=1, bins=25)
17 |
--------------------------------------------------------------------------------
/examples/spreadsheet_heatmap.py:
--------------------------------------------------------------------------------
1 | """
2 | Annotated heatmaps
3 | ==================
4 |
5 | """
6 | import matplotlib.pyplot as plt
7 | import seaborn as sns
8 | sns.set_theme()
9 |
10 | # Load the example flights dataset and convert to long-form
11 | flights_long = sns.load_dataset("flights")
12 | flights = (
13 | flights_long
14 | .pivot(index="month", columns="year", values="passengers")
15 | )
16 |
17 | # Draw a heatmap with the numeric values in each cell
18 | f, ax = plt.subplots(figsize=(9, 6))
19 | sns.heatmap(flights, annot=True, fmt="d", linewidths=.5, ax=ax)
20 |
--------------------------------------------------------------------------------
/examples/strip_regplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Regression fit over a strip plot
3 | ================================
4 |
5 | _thumb: .53, .5
6 | """
7 | import seaborn as sns
8 | sns.set_theme()
9 |
10 | mpg = sns.load_dataset("mpg")
11 | sns.catplot(
12 | data=mpg, x="cylinders", y="acceleration", hue="weight",
13 | native_scale=True, zorder=1
14 | )
15 | sns.regplot(
16 | data=mpg, x="cylinders", y="acceleration",
17 | scatter=False, truncate=False, order=2, color=".2",
18 | )
19 |
--------------------------------------------------------------------------------
/examples/structured_heatmap.py:
--------------------------------------------------------------------------------
1 | """
2 | Discovering structure in heatmap data
3 | =====================================
4 |
5 | _thumb: .3, .25
6 | """
7 | import pandas as pd
8 | import seaborn as sns
9 | sns.set_theme()
10 |
11 | # Load the brain networks example dataset
12 | df = sns.load_dataset("brain_networks", header=[0, 1, 2], index_col=0)
13 |
14 | # Select a subset of the networks
15 | used_networks = [1, 5, 6, 7, 8, 12, 13, 17]
16 | used_columns = (df.columns.get_level_values("network")
17 | .astype(int)
18 | .isin(used_networks))
19 | df = df.loc[:, used_columns]
20 |
21 | # Create a categorical palette to identify the networks
22 | network_pal = sns.husl_palette(8, s=.45)
23 | network_lut = dict(zip(map(str, used_networks), network_pal))
24 |
25 | # Convert the palette to vectors that will be drawn on the side of the matrix
26 | networks = df.columns.get_level_values("network")
27 | network_colors = pd.Series(networks, index=df.columns).map(network_lut)
28 |
29 | # Draw the full plot
30 | g = sns.clustermap(df.corr(), center=0, cmap="vlag",
31 | row_colors=network_colors, col_colors=network_colors,
32 | dendrogram_ratio=(.1, .2),
33 | cbar_pos=(.02, .32, .03, .2),
34 | linewidths=.75, figsize=(12, 13))
35 |
36 | g.ax_row_dendrogram.remove()
37 |
--------------------------------------------------------------------------------
/examples/three_variable_histogram.py:
--------------------------------------------------------------------------------
1 | """
2 | Trivariate histogram with two categorical variables
3 | ===================================================
4 |
5 | _thumb: .32, .55
6 |
7 | """
8 | import seaborn as sns
9 | sns.set_theme(style="dark")
10 |
11 | diamonds = sns.load_dataset("diamonds")
12 | sns.displot(
13 | data=diamonds, x="price", y="color", col="clarity",
14 | log_scale=(True, False), col_wrap=4, height=4, aspect=.7,
15 | )
16 |
--------------------------------------------------------------------------------
/examples/timeseries_facets.py:
--------------------------------------------------------------------------------
1 | """
2 | Small multiple time series
3 | --------------------------
4 |
5 | _thumb: .42, .58
6 |
7 | """
8 | import seaborn as sns
9 |
10 | sns.set_theme(style="dark")
11 | flights = sns.load_dataset("flights")
12 |
13 | # Plot each year's time series in its own facet
14 | g = sns.relplot(
15 | data=flights,
16 | x="month", y="passengers", col="year", hue="year",
17 | kind="line", palette="crest", linewidth=4, zorder=5,
18 | col_wrap=3, height=2, aspect=1.5, legend=False,
19 | )
20 |
21 | # Iterate over each subplot to customize further
22 | for year, ax in g.axes_dict.items():
23 |
24 | # Add the title as an annotation within the plot
25 | ax.text(.8, .85, year, transform=ax.transAxes, fontweight="bold")
26 |
27 | # Plot every year's time series in the background
28 | sns.lineplot(
29 | data=flights, x="month", y="passengers", units="year",
30 | estimator=None, color=".7", linewidth=1, ax=ax,
31 | )
32 |
33 | # Reduce the frequency of the x axis ticks
34 | ax.set_xticks(ax.get_xticks()[::2])
35 |
36 | # Tweak the supporting aspects of the plot
37 | g.set_titles("")
38 | g.set_axis_labels("", "Passengers")
39 | g.tight_layout()
40 |
--------------------------------------------------------------------------------
/examples/wide_data_lineplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Lineplot from a wide-form dataset
3 | =================================
4 |
5 | _thumb: .52, .5
6 |
7 | """
8 | import numpy as np
9 | import pandas as pd
10 | import seaborn as sns
11 | sns.set_theme(style="whitegrid")
12 |
13 | rs = np.random.RandomState(365)
14 | values = rs.randn(365, 4).cumsum(axis=0)
15 | dates = pd.date_range("1 1 2016", periods=365, freq="D")
16 | data = pd.DataFrame(values, dates, columns=["A", "B", "C", "D"])
17 | data = data.rolling(7).mean()
18 |
19 | sns.lineplot(data=data, palette="tab10", linewidth=2.5)
20 |
--------------------------------------------------------------------------------
/examples/wide_form_violinplot.py:
--------------------------------------------------------------------------------
1 | """
2 | Violinplot from a wide-form dataset
3 | ===================================
4 |
5 | _thumb: .6, .45
6 | """
7 | import seaborn as sns
8 | import matplotlib.pyplot as plt
9 | sns.set_theme(style="whitegrid")
10 |
11 | # Load the example dataset of brain network correlations
12 | df = sns.load_dataset("brain_networks", header=[0, 1, 2], index_col=0)
13 |
14 | # Pull out a specific subset of networks
15 | used_networks = [1, 3, 4, 5, 6, 7, 8, 11, 12, 13, 16, 17]
16 | used_columns = (df.columns.get_level_values("network")
17 | .astype(int)
18 | .isin(used_networks))
19 | df = df.loc[:, used_columns]
20 |
21 | # Compute the correlation matrix and average over networks
22 | corr_df = df.corr().groupby(level="network").mean()
23 | corr_df.index = corr_df.index.astype(int)
24 | corr_df = corr_df.sort_index().T
25 |
26 | # Set up the matplotlib figure
27 | f, ax = plt.subplots(figsize=(11, 6))
28 |
29 | # Draw a violinplot with a narrower bandwidth than the default
30 | sns.violinplot(data=corr_df, bw_adjust=.5, cut=1, linewidth=1, palette="Set3")
31 |
32 | # Finalize the figure
33 | ax.set(ylim=(-.7, 1.05))
34 | sns.despine(left=True, bottom=True)
35 |
--------------------------------------------------------------------------------
/licences/APPDIRS_LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2005-2010 ActiveState Software Inc.
2 | Copyright (c) 2013 Eddy Petrișor
3 |
4 | This file is directly from
5 | https://github.com/ActiveState/appdirs/blob/3fe6a83776843a46f20c2e5587afcffe05e03b39/appdirs.py
6 |
7 | The license of https://github.com/ActiveState/appdirs copied below:
8 |
9 |
10 | # This is the MIT license
11 |
12 | Copyright (c) 2010 ActiveState Software Inc.
13 |
14 | Permission is hereby granted, free of charge, to any person obtaining a
15 | copy of this software and associated documentation files (the
16 | "Software"), to deal in the Software without restriction, including
17 | without limitation the rights to use, copy, modify, merge, publish,
18 | distribute, sublicense, and/or sell copies of the Software, and to
19 | permit persons to whom the Software is furnished to do so, subject to
20 | the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included
23 | in all copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
29 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
30 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 |
--------------------------------------------------------------------------------
/licences/HUSL_LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012 Alexei Boronine
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/licences/NUMPYDOC_LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in
11 | the documentation and/or other materials provided with the
12 | distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/licences/PACKAGING_LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) Donald Stufft and individual contributors.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/licences/SCIPY_LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2001-2002 Enthought, Inc. 2003-2019, SciPy Developers.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above
12 | copyright notice, this list of conditions and the following
13 | disclaimer in the documentation and/or other materials provided
14 | with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived
18 | from this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["flit_core >=3.2,<4"]
3 | build-backend = "flit_core.buildapi"
4 |
5 | [project]
6 | name = "seaborn"
7 | description = "Statistical data visualization"
8 | authors = [{name = "Michael Waskom", email = "mwaskom@gmail.com"}]
9 | readme = "README.md"
10 | license = {file = "LICENSE.md"}
11 | dynamic = ["version"]
12 | classifiers = [
13 | "Intended Audience :: Science/Research",
14 | "Programming Language :: Python :: 3.8",
15 | "Programming Language :: Python :: 3.9",
16 | "Programming Language :: Python :: 3.10",
17 | "Programming Language :: Python :: 3.11",
18 | "Programming Language :: Python :: 3.12",
19 | "License :: OSI Approved :: BSD License",
20 | "Topic :: Scientific/Engineering :: Visualization",
21 | "Topic :: Multimedia :: Graphics",
22 | "Operating System :: OS Independent",
23 | "Framework :: Matplotlib",
24 | ]
25 | requires-python = ">=3.8"
26 | dependencies = [
27 | "numpy>=1.20,!=1.24.0",
28 | "pandas>=1.2",
29 | "matplotlib>=3.4,!=3.6.1",
30 | ]
31 |
32 | [project.optional-dependencies]
33 | stats = [
34 | "scipy>=1.7",
35 | "statsmodels>=0.12",
36 | ]
37 | dev = [
38 | "pytest",
39 | "pytest-cov",
40 | "pytest-xdist",
41 | "flake8",
42 | "mypy",
43 | "pandas-stubs",
44 | "pre-commit",
45 | "flit",
46 | ]
47 | docs = [
48 | "numpydoc",
49 | "nbconvert",
50 | "ipykernel",
51 | "sphinx<6.0.0",
52 | "sphinx-copybutton",
53 | "sphinx-issues",
54 | "sphinx-design",
55 | "pyyaml",
56 | "pydata_sphinx_theme==0.10.0rc2",
57 | ]
58 |
59 | [project.urls]
60 | Source = "https://github.com/mwaskom/seaborn"
61 | Docs = "http://seaborn.pydata.org"
62 |
63 | [tool.flit.sdist]
64 | exclude = ["doc/_static/*.svg"]
65 |
66 | [tool.pytest.ini_options]
67 | filterwarnings = [
68 | "ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning",
69 | "ignore:\\s*Pyarrow will become a required dependency of pandas:DeprecationWarning",
70 | "ignore:datetime.datetime.utcfromtimestamp\\(\\) is deprecated:DeprecationWarning",
71 | ]
72 |
--------------------------------------------------------------------------------
/seaborn/__init__.py:
--------------------------------------------------------------------------------
1 | # Import seaborn objects
2 | from .rcmod import * # noqa: F401,F403
3 | from .utils import * # noqa: F401,F403
4 | from .palettes import * # noqa: F401,F403
5 | from .relational import * # noqa: F401,F403
6 | from .regression import * # noqa: F401,F403
7 | from .categorical import * # noqa: F401,F403
8 | from .distributions import * # noqa: F401,F403
9 | from .matrix import * # noqa: F401,F403
10 | from .miscplot import * # noqa: F401,F403
11 | from .axisgrid import * # noqa: F401,F403
12 | from .widgets import * # noqa: F401,F403
13 | from .colors import xkcd_rgb, crayons # noqa: F401
14 | from . import cm # noqa: F401
15 |
16 | # Capture the original matplotlib rcParams
17 | import matplotlib as mpl
18 | _orig_rc_params = mpl.rcParams.copy()
19 |
20 | # Define the seaborn version
21 | __version__ = "0.14.0.dev0"
22 |
--------------------------------------------------------------------------------
/seaborn/_core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/seaborn/_core/__init__.py
--------------------------------------------------------------------------------
/seaborn/_core/exceptions.py:
--------------------------------------------------------------------------------
1 | """
2 | Custom exceptions for the seaborn.objects interface.
3 |
4 | This is very lightweight, but it's a separate module to avoid circular imports.
5 |
6 | """
7 | from __future__ import annotations
8 |
9 |
10 | class PlotSpecError(RuntimeError):
11 | """
12 | Error class raised from seaborn.objects.Plot for compile-time failures.
13 |
14 | In the declarative Plot interface, exceptions may not be triggered immediately
15 | by bad user input (and validation at input time may not be possible). This class
16 | is used to signal that indirect dependency. It should be raised in an exception
17 | chain when compile-time operations fail with an error message providing useful
18 | context (e.g., scaling errors could specify the variable that failed.)
19 |
20 | """
21 | @classmethod
22 | def _during(cls, step: str, var: str = "") -> PlotSpecError:
23 | """
24 | Initialize the class to report the failure of a specific operation.
25 | """
26 | message = []
27 | if var:
28 | message.append(f"{step} failed for the `{var}` variable.")
29 | else:
30 | message.append(f"{step} failed.")
31 | message.append("See the traceback above for more information.")
32 | return cls(" ".join(message))
33 |
--------------------------------------------------------------------------------
/seaborn/_core/typing.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from collections.abc import Iterable, Mapping
4 | from datetime import date, datetime, timedelta
5 | from typing import Any, Optional, Union, Tuple, List, Dict
6 |
7 | from numpy import ndarray # TODO use ArrayLike?
8 | from pandas import Series, Index, Timestamp, Timedelta
9 | from matplotlib.colors import Colormap, Normalize
10 |
11 |
12 | ColumnName = Union[
13 | str, bytes, date, datetime, timedelta, bool, complex, Timestamp, Timedelta
14 | ]
15 | Vector = Union[Series, Index, ndarray]
16 |
17 | VariableSpec = Union[ColumnName, Vector, None]
18 | VariableSpecList = Union[List[VariableSpec], Index, None]
19 |
20 | # A DataSource can be an object implementing __dataframe__, or a Mapping
21 | # (and is optional in all contexts where it is used).
22 | # I don't think there's an abc for "has __dataframe__", so we type as object
23 | # but keep the (slightly odd) Union alias for better user-facing annotations.
24 | DataSource = Union[object, Mapping, None]
25 |
26 | OrderSpec = Union[Iterable, None] # TODO technically str is iterable
27 | NormSpec = Union[Tuple[Optional[float], Optional[float]], Normalize, None]
28 |
29 | # TODO for discrete mappings, it would be ideal to use a parameterized type
30 | # as the dict values / list entries should be of specific type(s) for each method
31 | PaletteSpec = Union[str, list, dict, Colormap, None]
32 | DiscreteValueSpec = Union[dict, list, None]
33 | ContinuousValueSpec = Union[
34 | Tuple[float, float], List[float], Dict[Any, float], None,
35 | ]
36 |
37 |
38 | class Default:
39 | def __repr__(self):
40 | return ""
41 |
42 |
43 | class Deprecated:
44 | def __repr__(self):
45 | return ""
46 |
47 |
48 | default = Default()
49 | deprecated = Deprecated()
50 |
--------------------------------------------------------------------------------
/seaborn/_marks/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/seaborn/_marks/__init__.py
--------------------------------------------------------------------------------
/seaborn/_marks/text.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | from collections import defaultdict
3 | from dataclasses import dataclass
4 |
5 | import numpy as np
6 | import matplotlib as mpl
7 | from matplotlib.transforms import ScaledTranslation
8 |
9 | from seaborn._marks.base import (
10 | Mark,
11 | Mappable,
12 | MappableFloat,
13 | MappableString,
14 | MappableColor,
15 | resolve_properties,
16 | resolve_color,
17 | document_properties,
18 | )
19 |
20 |
21 | @document_properties
22 | @dataclass
23 | class Text(Mark):
24 | """
25 | A textual mark to annotate or represent data values.
26 |
27 | Examples
28 | --------
29 | .. include:: ../docstrings/objects.Text.rst
30 |
31 | """
32 | text: MappableString = Mappable("")
33 | color: MappableColor = Mappable("k")
34 | alpha: MappableFloat = Mappable(1)
35 | fontsize: MappableFloat = Mappable(rc="font.size")
36 | halign: MappableString = Mappable("center")
37 | valign: MappableString = Mappable("center_baseline")
38 | offset: MappableFloat = Mappable(4)
39 |
40 | def _plot(self, split_gen, scales, orient):
41 |
42 | ax_data = defaultdict(list)
43 |
44 | for keys, data, ax in split_gen():
45 |
46 | vals = resolve_properties(self, keys, scales)
47 | color = resolve_color(self, keys, "", scales)
48 |
49 | halign = vals["halign"]
50 | valign = vals["valign"]
51 | fontsize = vals["fontsize"]
52 | offset = vals["offset"] / 72
53 |
54 | offset_trans = ScaledTranslation(
55 | {"right": -offset, "left": +offset}.get(halign, 0),
56 | {"top": -offset, "bottom": +offset, "baseline": +offset}.get(valign, 0),
57 | ax.figure.dpi_scale_trans,
58 | )
59 |
60 | for row in data.to_dict("records"):
61 | artist = mpl.text.Text(
62 | x=row["x"],
63 | y=row["y"],
64 | text=str(row.get("text", vals["text"])),
65 | color=color,
66 | fontsize=fontsize,
67 | horizontalalignment=halign,
68 | verticalalignment=valign,
69 | transform=ax.transData + offset_trans,
70 | **self.artist_kws,
71 | )
72 | ax.add_artist(artist)
73 | ax_data[ax].append([row["x"], row["y"]])
74 |
75 | for ax, ax_vals in ax_data.items():
76 | ax.update_datalim(np.array(ax_vals))
77 |
--------------------------------------------------------------------------------
/seaborn/_stats/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/seaborn/_stats/__init__.py
--------------------------------------------------------------------------------
/seaborn/_stats/base.py:
--------------------------------------------------------------------------------
1 | """Base module for statistical transformations."""
2 | from __future__ import annotations
3 | from collections.abc import Iterable
4 | from dataclasses import dataclass
5 | from typing import ClassVar, Any
6 | import warnings
7 |
8 | from typing import TYPE_CHECKING
9 | if TYPE_CHECKING:
10 | from pandas import DataFrame
11 | from seaborn._core.groupby import GroupBy
12 | from seaborn._core.scales import Scale
13 |
14 |
15 | @dataclass
16 | class Stat:
17 | """Base class for objects that apply statistical transformations."""
18 |
19 | # The class supports a partial-function application pattern. The object is
20 | # initialized with desired parameters and the result is a callable that
21 | # accepts and returns dataframes.
22 |
23 | # The statistical transformation logic should not add any state to the instance
24 | # beyond what is defined with the initialization parameters.
25 |
26 | # Subclasses can declare whether the orient dimension should be used in grouping
27 | # TODO consider whether this should be a parameter. Motivating example:
28 | # use the same KDE class violin plots and univariate density estimation.
29 | # In the former case, we would expect separate densities for each unique
30 | # value on the orient axis, but we would not in the latter case.
31 | group_by_orient: ClassVar[bool] = False
32 |
33 | def _check_param_one_of(self, param: str, options: Iterable[Any]) -> None:
34 | """Raise when parameter value is not one of a specified set."""
35 | value = getattr(self, param)
36 | if value not in options:
37 | *most, last = options
38 | option_str = ", ".join(f"{x!r}" for x in most[:-1]) + f" or {last!r}"
39 | err = " ".join([
40 | f"The `{param}` parameter for `{self.__class__.__name__}` must be",
41 | f"one of {option_str}; not {value!r}.",
42 | ])
43 | raise ValueError(err)
44 |
45 | def _check_grouping_vars(
46 | self, param: str, data_vars: list[str], stacklevel: int = 2,
47 | ) -> None:
48 | """Warn if vars are named in parameter without being present in the data."""
49 | param_vars = getattr(self, param)
50 | undefined = set(param_vars) - set(data_vars)
51 | if undefined:
52 | param = f"{self.__class__.__name__}.{param}"
53 | names = ", ".join(f"{x!r}" for x in undefined)
54 | msg = f"Undefined variable(s) passed for {param}: {names}."
55 | warnings.warn(msg, stacklevel=stacklevel)
56 |
57 | def __call__(
58 | self,
59 | data: DataFrame,
60 | groupby: GroupBy,
61 | orient: str,
62 | scales: dict[str, Scale],
63 | ) -> DataFrame:
64 | """Apply statistical transform to data subgroups and return combined result."""
65 | return data
66 |
--------------------------------------------------------------------------------
/seaborn/_stats/order.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import annotations
3 | from dataclasses import dataclass
4 | from typing import ClassVar, cast
5 | try:
6 | from typing import Literal
7 | except ImportError:
8 | from typing_extensions import Literal # type: ignore
9 |
10 | import numpy as np
11 | from pandas import DataFrame
12 |
13 | from seaborn._core.scales import Scale
14 | from seaborn._core.groupby import GroupBy
15 | from seaborn._stats.base import Stat
16 | from seaborn.utils import _version_predates
17 |
18 |
19 | # From https://github.com/numpy/numpy/blob/main/numpy/lib/function_base.pyi
20 | _MethodKind = Literal[
21 | "inverted_cdf",
22 | "averaged_inverted_cdf",
23 | "closest_observation",
24 | "interpolated_inverted_cdf",
25 | "hazen",
26 | "weibull",
27 | "linear",
28 | "median_unbiased",
29 | "normal_unbiased",
30 | "lower",
31 | "higher",
32 | "midpoint",
33 | "nearest",
34 | ]
35 |
36 |
37 | @dataclass
38 | class Perc(Stat):
39 | """
40 | Replace observations with percentile values.
41 |
42 | Parameters
43 | ----------
44 | k : list of numbers or int
45 | If a list of numbers, this gives the percentiles (in [0, 100]) to compute.
46 | If an integer, compute `k` evenly-spaced percentiles between 0 and 100.
47 | For example, `k=5` computes the 0, 25, 50, 75, and 100th percentiles.
48 | method : str
49 | Method for interpolating percentiles between observed datapoints.
50 | See :func:`numpy.percentile` for valid options and more information.
51 |
52 | Examples
53 | --------
54 | .. include:: ../docstrings/objects.Perc.rst
55 |
56 | """
57 | k: int | list[float] = 5
58 | method: str = "linear"
59 |
60 | group_by_orient: ClassVar[bool] = True
61 |
62 | def _percentile(self, data: DataFrame, var: str) -> DataFrame:
63 |
64 | k = list(np.linspace(0, 100, self.k)) if isinstance(self.k, int) else self.k
65 | method = cast(_MethodKind, self.method)
66 | values = data[var].dropna()
67 | if _version_predates(np, "1.22"):
68 | res = np.percentile(values, k, interpolation=method) # type: ignore
69 | else:
70 | res = np.percentile(data[var].dropna(), k, method=method)
71 | return DataFrame({var: res, "percentile": k})
72 |
73 | def __call__(
74 | self, data: DataFrame, groupby: GroupBy, orient: str, scales: dict[str, Scale],
75 | ) -> DataFrame:
76 |
77 | var = {"x": "y", "y": "x"}[orient]
78 | return groupby.apply(data, self._percentile, var)
79 |
--------------------------------------------------------------------------------
/seaborn/_stats/regression.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 | from dataclasses import dataclass
3 |
4 | import numpy as np
5 | import pandas as pd
6 |
7 | from seaborn._stats.base import Stat
8 |
9 |
10 | @dataclass
11 | class PolyFit(Stat):
12 | """
13 | Fit a polynomial of the given order and resample data onto predicted curve.
14 | """
15 | # This is a provisional class that is useful for building out functionality.
16 | # It may or may not change substantially in form or dissappear as we think
17 | # through the organization of the stats subpackage.
18 |
19 | order: int = 2
20 | gridsize: int = 100
21 |
22 | def _fit_predict(self, data):
23 |
24 | x = data["x"]
25 | y = data["y"]
26 | if x.nunique() <= self.order:
27 | # TODO warn?
28 | xx = yy = []
29 | else:
30 | p = np.polyfit(x, y, self.order)
31 | xx = np.linspace(x.min(), x.max(), self.gridsize)
32 | yy = np.polyval(p, xx)
33 |
34 | return pd.DataFrame(dict(x=xx, y=yy))
35 |
36 | # TODO we should have a way of identifying the method that will be applied
37 | # and then only define __call__ on a base-class of stats with this pattern
38 |
39 | def __call__(self, data, groupby, orient, scales):
40 |
41 | return (
42 | groupby
43 | .apply(data.dropna(subset=["x", "y"]), self._fit_predict)
44 | )
45 |
46 |
47 | @dataclass
48 | class OLSFit(Stat):
49 |
50 | ...
51 |
--------------------------------------------------------------------------------
/seaborn/_testing.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib as mpl
3 | from matplotlib.colors import to_rgb, to_rgba
4 | from numpy.testing import assert_array_equal
5 |
6 |
7 | USE_PROPS = [
8 | "alpha",
9 | "edgecolor",
10 | "facecolor",
11 | "fill",
12 | "hatch",
13 | "height",
14 | "linestyle",
15 | "linewidth",
16 | "paths",
17 | "xy",
18 | "xydata",
19 | "sizes",
20 | "zorder",
21 | ]
22 |
23 |
24 | def assert_artists_equal(list1, list2):
25 |
26 | assert len(list1) == len(list2)
27 | for a1, a2 in zip(list1, list2):
28 | assert a1.__class__ == a2.__class__
29 | prop1 = a1.properties()
30 | prop2 = a2.properties()
31 | for key in USE_PROPS:
32 | if key not in prop1:
33 | continue
34 | v1 = prop1[key]
35 | v2 = prop2[key]
36 | if key == "paths":
37 | for p1, p2 in zip(v1, v2):
38 | assert_array_equal(p1.vertices, p2.vertices)
39 | assert_array_equal(p1.codes, p2.codes)
40 | elif key == "color":
41 | v1 = mpl.colors.to_rgba(v1)
42 | v2 = mpl.colors.to_rgba(v2)
43 | assert v1 == v2
44 | elif isinstance(v1, np.ndarray):
45 | assert_array_equal(v1, v2)
46 | else:
47 | assert v1 == v2
48 |
49 |
50 | def assert_legends_equal(leg1, leg2):
51 |
52 | assert leg1.get_title().get_text() == leg2.get_title().get_text()
53 | for t1, t2 in zip(leg1.get_texts(), leg2.get_texts()):
54 | assert t1.get_text() == t2.get_text()
55 |
56 | assert_artists_equal(
57 | leg1.get_patches(), leg2.get_patches(),
58 | )
59 | assert_artists_equal(
60 | leg1.get_lines(), leg2.get_lines(),
61 | )
62 |
63 |
64 | def assert_plots_equal(ax1, ax2, labels=True):
65 |
66 | assert_artists_equal(ax1.patches, ax2.patches)
67 | assert_artists_equal(ax1.lines, ax2.lines)
68 | assert_artists_equal(ax1.collections, ax2.collections)
69 |
70 | if labels:
71 | assert ax1.get_xlabel() == ax2.get_xlabel()
72 | assert ax1.get_ylabel() == ax2.get_ylabel()
73 |
74 |
75 | def assert_colors_equal(a, b, check_alpha=True):
76 |
77 | def handle_array(x):
78 |
79 | if isinstance(x, np.ndarray):
80 | if x.ndim > 1:
81 | x = np.unique(x, axis=0).squeeze()
82 | if x.ndim > 1:
83 | raise ValueError("Color arrays must be 1 dimensional")
84 | return x
85 |
86 | a = handle_array(a)
87 | b = handle_array(b)
88 |
89 | f = to_rgba if check_alpha else to_rgb
90 | assert f(a) == f(b)
91 |
--------------------------------------------------------------------------------
/seaborn/colors/__init__.py:
--------------------------------------------------------------------------------
1 | from .xkcd_rgb import xkcd_rgb # noqa: F401
2 | from .crayons import crayons # noqa: F401
3 |
--------------------------------------------------------------------------------
/seaborn/external/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/seaborn/external/__init__.py
--------------------------------------------------------------------------------
/seaborn/miscplot.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib as mpl
3 | import matplotlib.pyplot as plt
4 | import matplotlib.ticker as ticker
5 |
6 | __all__ = ["palplot", "dogplot"]
7 |
8 |
9 | def palplot(pal, size=1):
10 | """Plot the values in a color palette as a horizontal array.
11 |
12 | Parameters
13 | ----------
14 | pal : sequence of matplotlib colors
15 | colors, i.e. as returned by seaborn.color_palette()
16 | size :
17 | scaling factor for size of plot
18 |
19 | """
20 | n = len(pal)
21 | _, ax = plt.subplots(1, 1, figsize=(n * size, size))
22 | ax.imshow(np.arange(n).reshape(1, n),
23 | cmap=mpl.colors.ListedColormap(list(pal)),
24 | interpolation="nearest", aspect="auto")
25 | ax.set_xticks(np.arange(n) - .5)
26 | ax.set_yticks([-.5, .5])
27 | # Ensure nice border between colors
28 | ax.set_xticklabels(["" for _ in range(n)])
29 | # The proper way to set no ticks
30 | ax.yaxis.set_major_locator(ticker.NullLocator())
31 |
32 |
33 | def dogplot(*_, **__):
34 | """Who's a good boy?"""
35 | from urllib.request import urlopen
36 | from io import BytesIO
37 |
38 | url = "https://github.com/mwaskom/seaborn-data/raw/master/png/img{}.png"
39 | pic = np.random.randint(2, 7)
40 | data = BytesIO(urlopen(url.format(pic)).read())
41 | img = plt.imread(data)
42 | f, ax = plt.subplots(figsize=(5, 5), dpi=100)
43 | f.subplots_adjust(0, 0, 1, 1)
44 | ax.imshow(img)
45 | ax.set_axis_off()
46 |
--------------------------------------------------------------------------------
/seaborn/objects.py:
--------------------------------------------------------------------------------
1 | """
2 | A declarative, object-oriented interface for creating statistical graphics.
3 |
4 | The seaborn.objects namespace contains a number of classes that can be composed
5 | together to build a customized visualization.
6 |
7 | The main object is :class:`Plot`, which is the starting point for all figures.
8 | Pass :class:`Plot` a dataset and specify assignments from its variables to
9 | roles in the plot. Build up the visualization by calling its methods.
10 |
11 | There are four other general types of objects in this interface:
12 |
13 | - :class:`Mark` subclasses, which create matplotlib artists for visualization
14 | - :class:`Stat` subclasses, which apply statistical transforms before plotting
15 | - :class:`Move` subclasses, which make further adjustments to reduce overplotting
16 |
17 | These classes are passed to :meth:`Plot.add` to define a layer in the plot.
18 | Each layer has a :class:`Mark` and optional :class:`Stat` and/or :class:`Move`.
19 | Plots can have multiple layers.
20 |
21 | The other general type of object is a :class:`Scale` subclass, which provide an
22 | interface for controlling the mappings between data values and visual properties.
23 | Pass :class:`Scale` objects to :meth:`Plot.scale`.
24 |
25 | See the documentation for other :class:`Plot` methods to learn about the many
26 | ways that a plot can be enhanced and customized.
27 |
28 | """
29 | from seaborn._core.plot import Plot # noqa: F401
30 |
31 | from seaborn._marks.base import Mark # noqa: F401
32 | from seaborn._marks.area import Area, Band # noqa: F401
33 | from seaborn._marks.bar import Bar, Bars # noqa: F401
34 | from seaborn._marks.dot import Dot, Dots # noqa: F401
35 | from seaborn._marks.line import Dash, Line, Lines, Path, Paths, Range # noqa: F401
36 | from seaborn._marks.text import Text # noqa: F401
37 |
38 | from seaborn._stats.base import Stat # noqa: F401
39 | from seaborn._stats.aggregation import Agg, Est # noqa: F401
40 | from seaborn._stats.counting import Count, Hist # noqa: F401
41 | from seaborn._stats.density import KDE # noqa: F401
42 | from seaborn._stats.order import Perc # noqa: F401
43 | from seaborn._stats.regression import PolyFit # noqa: F401
44 |
45 | from seaborn._core.moves import Dodge, Jitter, Norm, Shift, Stack, Move # noqa: F401
46 |
47 | from seaborn._core.scales import ( # noqa: F401
48 | Boolean, Continuous, Nominal, Temporal, Scale
49 | )
50 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length = 88
3 | exclude = seaborn/cm.py,seaborn/external
4 | ignore = E741,F522,W503
5 |
6 | [mypy]
7 | # Currently this ignores pandas and matplotlib
8 | # We may want to make custom stub files for the parts we use
9 | # I have found the available third party stubs to be less
10 | # complete than they would need to be useful
11 | ignore_missing_imports = True
12 |
13 | [coverage:run]
14 | omit =
15 | seaborn/widgets.py
16 | seaborn/external/*
17 | seaborn/colors/*
18 | seaborn/cm.py
19 | seaborn/conftest.py
20 |
21 | [coverage:report]
22 | exclude_lines =
23 | pragma: no cover
24 | if TYPE_CHECKING:
25 | raise NotImplementedError
26 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/tests/__init__.py
--------------------------------------------------------------------------------
/tests/_core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/tests/_core/__init__.py
--------------------------------------------------------------------------------
/tests/_core/test_rules.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 |
5 | import pytest
6 |
7 | from seaborn._core.rules import (
8 | VarType,
9 | variable_type,
10 | categorical_order,
11 | )
12 |
13 |
14 | def test_vartype_object():
15 |
16 | v = VarType("numeric")
17 | assert v == "numeric"
18 | assert v != "categorical"
19 | with pytest.raises(AssertionError):
20 | v == "number"
21 | with pytest.raises(AssertionError):
22 | VarType("date")
23 |
24 |
25 | def test_variable_type():
26 |
27 | s = pd.Series([1., 2., 3.])
28 | assert variable_type(s) == "numeric"
29 | assert variable_type(s.astype(int)) == "numeric"
30 | assert variable_type(s.astype(object)) == "numeric"
31 |
32 | s = pd.Series([1, 2, 3, np.nan], dtype=object)
33 | assert variable_type(s) == "numeric"
34 |
35 | s = pd.Series([np.nan, np.nan])
36 | assert variable_type(s) == "numeric"
37 |
38 | s = pd.Series([pd.NA, pd.NA])
39 | assert variable_type(s) == "numeric"
40 |
41 | s = pd.Series([1, 2, pd.NA], dtype="Int64")
42 | assert variable_type(s) == "numeric"
43 |
44 | s = pd.Series([1, 2, pd.NA], dtype=object)
45 | assert variable_type(s) == "numeric"
46 |
47 | s = pd.Series(["1", "2", "3"])
48 | assert variable_type(s) == "categorical"
49 |
50 | s = pd.Series([True, False, False])
51 | assert variable_type(s) == "numeric"
52 | assert variable_type(s, boolean_type="categorical") == "categorical"
53 | assert variable_type(s, boolean_type="boolean") == "boolean"
54 |
55 | # This should arguably be datmetime, but we don't currently handle it correctly
56 | # Test is mainly asserting that this doesn't fail on the boolean check.
57 | s = pd.timedelta_range(1, periods=3, freq="D").to_series()
58 | assert variable_type(s) == "categorical"
59 |
60 | s_cat = s.astype("category")
61 | assert variable_type(s_cat, boolean_type="categorical") == "categorical"
62 | assert variable_type(s_cat, boolean_type="numeric") == "categorical"
63 | assert variable_type(s_cat, boolean_type="boolean") == "categorical"
64 |
65 | s = pd.Series([1, 0, 0])
66 | assert variable_type(s, boolean_type="boolean") == "boolean"
67 | assert variable_type(s, boolean_type="boolean", strict_boolean=True) == "numeric"
68 |
69 | s = pd.Series([1, 0, 0])
70 | assert variable_type(s, boolean_type="boolean") == "boolean"
71 |
72 | s = pd.Series([pd.Timestamp(1), pd.Timestamp(2)])
73 | assert variable_type(s) == "datetime"
74 | assert variable_type(s.astype(object)) == "datetime"
75 |
76 |
77 | def test_categorical_order():
78 |
79 | x = pd.Series(["a", "c", "c", "b", "a", "d"])
80 | y = pd.Series([3, 2, 5, 1, 4])
81 | order = ["a", "b", "c", "d"]
82 |
83 | out = categorical_order(x)
84 | assert out == ["a", "c", "b", "d"]
85 |
86 | out = categorical_order(x, order)
87 | assert out == order
88 |
89 | out = categorical_order(x, ["b", "a"])
90 | assert out == ["b", "a"]
91 |
92 | out = categorical_order(y)
93 | assert out == [1, 2, 3, 4, 5]
94 |
95 | out = categorical_order(pd.Series(y))
96 | assert out == [1, 2, 3, 4, 5]
97 |
98 | y_cat = pd.Series(pd.Categorical(y, y))
99 | out = categorical_order(y_cat)
100 | assert out == list(y)
101 |
102 | x = pd.Series(x).astype("category")
103 | out = categorical_order(x)
104 | assert out == list(x.cat.categories)
105 |
106 | out = categorical_order(x, ["b", "a"])
107 | assert out == ["b", "a"]
108 |
109 | x = pd.Series(["a", np.nan, "c", "c", "b", "a", "d"])
110 | out = categorical_order(x)
111 | assert out == ["a", "c", "b", "d"]
112 |
--------------------------------------------------------------------------------
/tests/_marks/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/tests/_marks/__init__.py
--------------------------------------------------------------------------------
/tests/_stats/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mwaskom/seaborn/86b5481ca47cb46d3b3e079a5ed9b9fb46e315ef/tests/_stats/__init__.py
--------------------------------------------------------------------------------
/tests/_stats/test_order.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 |
5 | import pytest
6 | from numpy.testing import assert_array_equal
7 |
8 | from seaborn._core.groupby import GroupBy
9 | from seaborn._stats.order import Perc
10 | from seaborn.utils import _version_predates
11 |
12 |
13 | class Fixtures:
14 |
15 | @pytest.fixture
16 | def df(self, rng):
17 | return pd.DataFrame(dict(x="", y=rng.normal(size=30)))
18 |
19 | def get_groupby(self, df, orient):
20 | # TODO note, copied from aggregation
21 | other = {"x": "y", "y": "x"}[orient]
22 | cols = [c for c in df if c != other]
23 | return GroupBy(cols)
24 |
25 |
26 | class TestPerc(Fixtures):
27 |
28 | def test_int_k(self, df):
29 |
30 | ori = "x"
31 | gb = self.get_groupby(df, ori)
32 | res = Perc(3)(df, gb, ori, {})
33 | percentiles = [0, 50, 100]
34 | assert_array_equal(res["percentile"], percentiles)
35 | assert_array_equal(res["y"], np.percentile(df["y"], percentiles))
36 |
37 | def test_list_k(self, df):
38 |
39 | ori = "x"
40 | gb = self.get_groupby(df, ori)
41 | percentiles = [0, 20, 100]
42 | res = Perc(k=percentiles)(df, gb, ori, {})
43 | assert_array_equal(res["percentile"], percentiles)
44 | assert_array_equal(res["y"], np.percentile(df["y"], percentiles))
45 |
46 | def test_orientation(self, df):
47 |
48 | df = df.rename(columns={"x": "y", "y": "x"})
49 | ori = "y"
50 | gb = self.get_groupby(df, ori)
51 | res = Perc(k=3)(df, gb, ori, {})
52 | assert_array_equal(res["x"], np.percentile(df["x"], [0, 50, 100]))
53 |
54 | def test_method(self, df):
55 |
56 | ori = "x"
57 | gb = self.get_groupby(df, ori)
58 | method = "nearest"
59 | res = Perc(k=5, method=method)(df, gb, ori, {})
60 | percentiles = [0, 25, 50, 75, 100]
61 | if _version_predates(np, "1.22.0"):
62 | expected = np.percentile(df["y"], percentiles, interpolation=method)
63 | else:
64 | expected = np.percentile(df["y"], percentiles, method=method)
65 | assert_array_equal(res["y"], expected)
66 |
67 | def test_grouped(self, df, rng):
68 |
69 | ori = "x"
70 | df = df.assign(x=rng.choice(["a", "b", "c"], len(df)))
71 | gb = self.get_groupby(df, ori)
72 | k = [10, 90]
73 | res = Perc(k)(df, gb, ori, {})
74 | for x, res_x in res.groupby("x"):
75 | assert_array_equal(res_x["percentile"], k)
76 | expected = np.percentile(df.loc[df["x"] == x, "y"], k)
77 | assert_array_equal(res_x["y"], expected)
78 |
79 | def test_with_na(self, df):
80 |
81 | ori = "x"
82 | df.loc[:5, "y"] = np.nan
83 | gb = self.get_groupby(df, ori)
84 | k = [10, 90]
85 | res = Perc(k)(df, gb, ori, {})
86 | expected = np.percentile(df["y"].dropna(), k)
87 | assert_array_equal(res["y"], expected)
88 |
--------------------------------------------------------------------------------
/tests/_stats/test_regression.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 |
5 | import pytest
6 | from numpy.testing import assert_array_equal, assert_array_almost_equal
7 | from pandas.testing import assert_frame_equal
8 |
9 | from seaborn._core.groupby import GroupBy
10 | from seaborn._stats.regression import PolyFit
11 |
12 |
13 | class TestPolyFit:
14 |
15 | @pytest.fixture
16 | def df(self, rng):
17 |
18 | n = 100
19 | return pd.DataFrame(dict(
20 | x=rng.normal(0, 1, n),
21 | y=rng.normal(0, 1, n),
22 | color=rng.choice(["a", "b", "c"], n),
23 | group=rng.choice(["x", "y"], n),
24 | ))
25 |
26 | def test_no_grouper(self, df):
27 |
28 | groupby = GroupBy(["group"])
29 | res = PolyFit(order=1, gridsize=100)(df[["x", "y"]], groupby, "x", {})
30 |
31 | assert_array_equal(res.columns, ["x", "y"])
32 |
33 | grid = np.linspace(df["x"].min(), df["x"].max(), 100)
34 | assert_array_equal(res["x"], grid)
35 | assert_array_almost_equal(
36 | res["y"].diff().diff().dropna(), np.zeros(grid.size - 2)
37 | )
38 |
39 | def test_one_grouper(self, df):
40 |
41 | groupby = GroupBy(["group"])
42 | gridsize = 50
43 | res = PolyFit(gridsize=gridsize)(df, groupby, "x", {})
44 |
45 | assert res.columns.to_list() == ["x", "y", "group"]
46 |
47 | ngroups = df["group"].nunique()
48 | assert_array_equal(res.index, np.arange(ngroups * gridsize))
49 |
50 | for _, part in res.groupby("group"):
51 | grid = np.linspace(part["x"].min(), part["x"].max(), gridsize)
52 | assert_array_equal(part["x"], grid)
53 | assert part["y"].diff().diff().dropna().abs().gt(0).all()
54 |
55 | def test_missing_data(self, df):
56 |
57 | groupby = GroupBy(["group"])
58 | df.iloc[5:10] = np.nan
59 | res1 = PolyFit()(df[["x", "y"]], groupby, "x", {})
60 | res2 = PolyFit()(df[["x", "y"]].dropna(), groupby, "x", {})
61 | assert_frame_equal(res1, res2)
62 |
--------------------------------------------------------------------------------
/tests/test_docstrings.py:
--------------------------------------------------------------------------------
1 | from seaborn._docstrings import DocstringComponents
2 |
3 |
4 | EXAMPLE_DICT = dict(
5 | param_a="""
6 | a : str
7 | The first parameter.
8 | """,
9 | )
10 |
11 |
12 | class ExampleClass:
13 | def example_method(self):
14 | """An example method.
15 |
16 | Parameters
17 | ----------
18 | a : str
19 | A method parameter.
20 |
21 | """
22 |
23 |
24 | def example_func():
25 | """An example function.
26 |
27 | Parameters
28 | ----------
29 | a : str
30 | A function parameter.
31 |
32 | """
33 |
34 |
35 | class TestDocstringComponents:
36 |
37 | def test_from_dict(self):
38 |
39 | obj = DocstringComponents(EXAMPLE_DICT)
40 | assert obj.param_a == "a : str\n The first parameter."
41 |
42 | def test_from_nested_components(self):
43 |
44 | obj_inner = DocstringComponents(EXAMPLE_DICT)
45 | obj_outer = DocstringComponents.from_nested_components(inner=obj_inner)
46 | assert obj_outer.inner.param_a == "a : str\n The first parameter."
47 |
48 | def test_from_function(self):
49 |
50 | obj = DocstringComponents.from_function_params(example_func)
51 | assert obj.a == "a : str\n A function parameter."
52 |
53 | def test_from_method(self):
54 |
55 | obj = DocstringComponents.from_function_params(
56 | ExampleClass.example_method
57 | )
58 | assert obj.a == "a : str\n A method parameter."
59 |
--------------------------------------------------------------------------------
/tests/test_miscplot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | from seaborn import miscplot as misc
4 | from seaborn.palettes import color_palette
5 | from .test_utils import _network
6 |
7 |
8 | class TestPalPlot:
9 | """Test the function that visualizes a color palette."""
10 | def test_palplot_size(self):
11 |
12 | pal4 = color_palette("husl", 4)
13 | misc.palplot(pal4)
14 | size4 = plt.gcf().get_size_inches()
15 | assert tuple(size4) == (4, 1)
16 |
17 | pal5 = color_palette("husl", 5)
18 | misc.palplot(pal5)
19 | size5 = plt.gcf().get_size_inches()
20 | assert tuple(size5) == (5, 1)
21 |
22 | palbig = color_palette("husl", 3)
23 | misc.palplot(palbig, 2)
24 | sizebig = plt.gcf().get_size_inches()
25 | assert tuple(sizebig) == (6, 2)
26 |
27 |
28 | class TestDogPlot:
29 |
30 | @_network(url="https://github.com/mwaskom/seaborn-data")
31 | def test_dogplot(self):
32 | misc.dogplot()
33 | ax = plt.gca()
34 | assert len(ax.images) == 1
35 |
--------------------------------------------------------------------------------
/tests/test_objects.py:
--------------------------------------------------------------------------------
1 | import seaborn.objects
2 | from seaborn._core.plot import Plot
3 | from seaborn._core.moves import Move
4 | from seaborn._core.scales import Scale
5 | from seaborn._marks.base import Mark
6 | from seaborn._stats.base import Stat
7 |
8 |
9 | def test_objects_namespace():
10 |
11 | for name in dir(seaborn.objects):
12 | if not name.startswith("__"):
13 | obj = getattr(seaborn.objects, name)
14 | assert issubclass(obj, (Plot, Mark, Stat, Move, Scale))
15 |
--------------------------------------------------------------------------------