---
jupytext:
  formats: content_md///md:myst,content///ipynb
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
    jupytext_version: 1.14.4
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
---

+++ {"user_expressions": []}

(visualization:matplotlib:seaborn)=
# Seaborn

Seaborn is a Python library based on Matplotlib. It provides two useful features:

* different pre-defined styles for Matplotlib figures,
* lots of functions for visualizing complex datasets.

```{code-cell} ipython3
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
```

+++ {"user_expressions": []}

The reason for importing as `sns` is somewhat vague. `sns` are the initials of [Samuel Norman Seaborn](https://en.wikipedia.org/wiki/Sam_Seaborn), a fictional television character. See also [issue #229 in Seaborns Github repository](https://github.com/mwaskom/seaborn/issues/229).

```{code-cell} ipython3
sns.set_style('darkgrid')
fig, ax = plt.subplots()
x = [1, 2]
y = [1, 2]
ax.plot(x, y)
plt.show()
```

+++ {"user_expressions": []}

Seaborn also supports different scalings for different usecases. Scaling is set with `sns.set_context` and one of the string arguments `paper`, `notebook`, `talk`, `poster`, where `notebook` is the default. Different scalings allow for almost identical code to create figures for different channels of publication.

```{code-cell} ipython3
sns.set_context('talk')
fig, ax = plt.subplots()
x = [1, 2]
y = [1, 2]
ax.plot(x, y)
plt.show()
```

+++ {"user_expressions": []}

## Plots for Exploring Data Sets

Seaborn comes with lots of functions which take a whole data set (Pandas data frame) and create complex visualizations of the dataset. To get an overview have a look at the [official Seaborn tutorials](https://seaborn.pydata.org/tutorial.html) and at the [Seaborn gallery](https://seaborn.pydata.org/examples/index.html).

```{code-cell} ipython3
sns.set_context('notebook')
rng = np.random.default_rng(0)

# parameters for point clouds
means = [[5, 0, 0], [-5, 2, 0], [0, -3, 5]] # mean vectors
covs = [[[1, 1, 0], [1, 1, 0], [0, 0, 1]],
        [[10, 2, 0], [2, 10, 2], [0, 2, 10]],
        [[0.1, 0, 0], [0, 3, 3], [0, 3, 7]]] # covariance matrices
names = ['cloud A', 'cloud B', 'cloud C'] # names
ns = [100, 1000, 100] # samples per cloud

# create data frame with named samples from each cloud
clouds = []
for (mean, cov, name, n) in zip(means, covs, names, ns):
    x, y, z = rng.multivariate_normal(mean, cov, n).T
    cloud_data = pd.DataFrame(np.asarray([x, y, z]).T, columns=['x', 'y', 'z'])
    cloud_data['name'] = name
    clouds.append(cloud_data)
data = pd.concat(clouds)

# show data frame structure    
display(data)

# plot pairwise relations with Seaborn
sns.pairplot(data, hue='name', hue_order=['cloud B', 'cloud A', 'cloud C'])
plt.show()
```
