Unexpected Seaborn
Notebook Setup¶
Load utility to display the environment , and my formatter
%load_ext watermark
%load_ext lab_black
All imports go here
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
Using Seaborn¶
Set the default Seaborn style as the default
sns.set()
List Seaborn in-built datasets. I am sure that if I updated my Seaborn and / or BeautifulSoup packages via conda
, the warning message would go away(?).
sns.get_dataset_names()
Load a dataset that we can play with
data = sns.load_dataset(name='tips')
data.head()
Gotcha 1: Axes Styles¶
The code below is WRONG (just in case somebody decides to cut and paste it).
My mental model was that the axes_style
call applied to subsequent plotting operations with a given axes obect.
Thus, I was very surprised that all five styles (as show below) came out exactly the same. I must admit I stared for quiet a while trying to find subtle differences.
fig, ax = plt.subplots(nrows=2, ncols=3)
with sns.axes_style("whitegrid"):
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax[0, 0]
)
ax[0, 0].set_title('whitegrid')
# end with
with sns.axes_style("darkgrid"):
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax[1, 0]
)
ax[1, 0].set_title('darkgrid')
# end with
with sns.axes_style("dark"):
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax[0, 1]
)
ax[0, 1].set_title('dark')
# end with
with sns.axes_style("white"):
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax[1, 1]
)
ax[1, 1].set_title('white')
# end with
with sns.axes_style("ticks"):
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax[0, 2]
)
ax[0, 2].set_title('ticks')
# end with
fig.suptitle('Seaborn Styles')
In fact, the axes_style
call sets the properties of Axes objects created after the call.
The appropriate strategy is to create a Figure object, and after the axes_style
call, create a new Axes object, and add it to the Figure object.
fig = plt.figure(figsize=(12, 12))
gs = fig.add_gridspec(2, 3)
with sns.axes_style("whitegrid"):
ax = fig.add_subplot(gs[0, 0])
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax
)
ax.set_title('whitegrid')
# end with
with sns.axes_style("darkgrid"):
ax = fig.add_subplot(gs[0, 1])
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax
)
ax.set_title('darkgrid')
# end with
with sns.axes_style("dark"):
ax = fig.add_subplot(gs[1, 0])
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax
)
ax.set_title('dark')
# end with
with sns.axes_style("white"):
ax = fig.add_subplot(gs[1, 1])
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax
)
ax.set_title('white')
# end with
with sns.axes_style("ticks"):
ax = fig.add_subplot(gs[0, 2])
sns.scatterplot(
x='total_bill', y='tip', data=data, ax=ax
)
ax.set_title('ticks')
# end with
fig.suptitle('Seaborn Styles')
Gotcha 2: Set_Context¶
The code below is WRONG. I had assumed that because setting an Axes style was a context manager operation, so setting a Seaborn Context would be done through a context manager too.
fig = plt.figure(figsize=(12, 12))
gs = fig.add_gridspec(2, 2)
with sns.set_context("paper"):
ax = fig.add_subplot(gs[0, 0])
sns.scatterplot(x='total_bill', y='tip', data=data, ax=ax)
ax.set_title('paper')
#end with
fig.suptitle('Seaborn Context Settings')
sns.set_context("notebook")
You have to explicitly reset the context after the initial set_context
call
fig = plt.figure(figsize=(12, 12))
gs = fig.add_gridspec(2, 2)
sns.set_context("paper")
ax = fig.add_subplot(gs[0, 0])
sns.scatterplot(x='total_bill', y='tip', data=data, ax=ax)
ax.set_title('paper')
sns.set_context("notebook")
ax = fig.add_subplot(gs[0, 1])
sns.scatterplot(x='total_bill', y='tip', data=data, ax=ax)
ax.set_title('notebook')
sns.set_context("talk")
ax = fig.add_subplot(gs[1, 0])
sns.scatterplot(x='total_bill', y='tip', data=data, ax=ax)
ax.set_title('talk')
sns.set_context("poster")
ax = fig.add_subplot(gs[1, 1])
sns.scatterplot(x='total_bill', y='tip', data=data, ax=ax)
ax.set_title('poster')
sns.set_context("notebook")
fig.suptitle('Seaborn Context Settings')
Useful Tricks¶
Summary Heatmaps¶
WE can use pandas
to get some nice Seaborn graphics. Suppose we want to learn the distribution on tables sizes across days of the week.
The pandas
snippet below counts the number of tables by party size, for each week day (we should probably rename the total_bill
column, as it is really a count)
data2 = (
data.groupby(by=['size', 'day'])['total_bill']
.count()
.reset_index()
)
data2.head()
We can now create a pivot table on day of week
data3 = data2.pivot(
index='size', columns='day', values='total_bill'
)
data3.head()
Now display it with Seaborn
ax = sns.heatmap(data3, annot=True, cmap='Blues')
ax.set_title('Count of party size by day of week')
We can also do the same trick to find the total revue by party size and day of week
data2 = (
data.groupby(by=['size', 'day'])['total_bill']
.sum()
.reset_index()
)
data3 = data2.pivot(
index='size', columns='day', values='total_bill'
)
ax = sns.heatmap(
data3, annot=True, cmap='Blues', fmt='3.0f'
)
ax.set_title('Revenue by party size by day of week')
Note the format specification: by default, Seaborn uses scientific notation for floats
More Heatmaps Tips¶
We create an array with a gradient, and random (normal) noise, and then display the result as a heatmap
ndata = [
[i + j + np.random.normal(0, 5) for i in range(25)]
for j in range(25)
]
sns.heatmap(ndata, cmap='viridis')
We can change the style of the heatmap: in the example below, we strip off the x and y axis labels, and set a shading style that de-emphasises the sharp edges. Non-standard shading seems to expose the underlying default grey background, so we set style as whitegrid
sns.set_style("whitegrid")
sns.heatmap(
ndata,
cmap='viridis',
shading='gouraud',
xticklabels=False,
yticklabels=False,
)
We can also go for a square aspect ratio, and reduce the size of the colorbar
sns.heatmap(
ndata,
cmap='viridis',
shading='gouraud',
xticklabels=False,
yticklabels=False,
square=True,
cbar_kws={'shrink': 0.5},
)
Environment¶
%watermark -h -iv
%watermark