Learn how to create beautiful and insightful charts with Python — the Quick, the Pretty, and the Awesome
By: Fabian Bosler
Tags: Data Visualization, Data Analysis, Data Science, Python, Towards Data Science

The Pretty: Advanced plotting with Seaborn

Photo by Pavel Nekoranec on Unsplash

Seaborn utilizes plotting defaults. To make sure that your results match mine, run the following commands.

sns.reset_defaults()

sns.set(

rc={'figure.figsize':(7,5)},

style="white" # nicer layout

)

Plotting univariate distributions

As mentioned before, I am a big fan of distributions. Histograms and kernel density distributions alike are potent ways of visualizing the critical features of a particular variable. Let’s look at how we generate distributions for a single variable or distributions of multiple variables in one chart.

Left chart: Histogram and kernel density estimation of “Life Ladder” for Asian countries in 2018; Right chart: Kernel density estimation of “Life Ladder” for five buckets of GDP per Capita — Money can buy happiness

Plotting bivariate distributions

Whenever I want to explore the relationship between two or multiple variables visually, it typically comes down to some form of scatterplot and an assessment of distributions. There are three variations of a conceptually similar plot. In each of those plots, the center graph (scatter, bivariate KDE, and hexbin) helps to understand the joint frequency distribution between two variables. Additionally, at the right and top border of the center graph, the marginal univariate distribution of the respective variable is depicted (as a KDE or histogram).

sns.jointplot(

x='Log GDP per capita',

y='Life Ladder',

data=data,

kind='scatter' # or 'kde' or 'hex'

)

Seaborn jointplot with scatter, bivariate kde, and hexbin in the center graph and marginal distributions left and on top of the center graph.

Scatterplot

A scatterplot is a way of visualizing the joint density distribution of two variables. We can throw a third variable in the mix by adding a hue and a fourth variable by adding the size parameter.

sns.scatterplot(

x='Log GDP per capita',

y='Life Ladder',

data=data[data['Year'] == 2018],

hue='Continent',

size='Gapminder Population'

) # both, hue and size are optional

sns.despine() # prettier layout

Log GDP per capita against Life Ladder, colors based on the continent and size on population

Violin plot

The violin plot is a combination of a box plot and a kernel density estimate. It plays a similar role as a box plot. It shows the distribution of quantitative data across categorical variables such that those distributions can be compared.

sns.set(

rc={'figure.figsize':(18,6)},

style="white"

) sns.violinplot(

x='Continent',

y='Life Ladder',

hue='Mean Log GDP per capita',

data=data

) sns.despine()

Violin plot where we plot continents against Life Ladder, we use the Mean Log GDP per capita to group the data. It looks like a higher GDP per capita makes for higher happiness

Pair plot

The Seaborn pair plot plots all combinations of two-variable scatter plots in a large grid. I typically feel like this is a bit of information overload, but it can help to spot patterns.

sns.set(

style="white",

palette="muted",

color_codes=True

) sns.pairplot(

data[data.Year == 2018][[

'Life Ladder','Log GDP per capita',

'Social support','Healthy life expectancy at birth',

'Freedom to make life choices','Generosity',

'Perceptions of corruption', 'Positive affect',

'Negative affect','Confidence in national government',

'Mean Log GDP per capita'

]].dropna(),

hue='Mean Log GDP per capita'

)

Seaborn scatterplot grid where all selected variables a scattered against every other variable in the lower and upper part of the grid, the diagonal contains a kde plot.

Facet Grids

Seaborn’s FacetGrid, to me, is one of the most convincing arguments to use Seaborn as it makes creating multi-plots a breeze. With the pair plot, we already have seen an example of a FacetGrid. The FacetGrid allows creating multiple charts segmented by variables. For example, the rows could be one variable (category of GDP per capita) and the columns another one (continents).

It does require a bit more customization (i.e., using matplotlib) then I’d personally like, but it is nonetheless compelling.

FacetGrid — line plots

g = sns.FacetGrid(

data.groupby(['Mean Log GDP per capita','Year','Continent'])['Life Ladder'].mean().reset_index(),

row='Mean Log GDP per capita',

col='Continent',

margin_titles=True

)

g = (g.map(plt.plot, 'Year','Life Ladder'))

Life Ladder on the Y-axis, Year on the X-axis. The grid’s columns are the continent, and the grid’s rows are the different levels of Mean Log GDP per capita. Overall things seem to be getting better for the countries with a Low Mean Log GDP per Capita in North America and the countries with a Medium or High Mean Log GDP per Capita in Europe

FacetGrid — histograms

g = sns.FacetGrid(data, col="Continent", col_wrap=3,height=4)

g = (g.map(plt.hist, "Life Ladder",bins=np.arange(2,9,0.5)))

FacetGrid with a histogram of LifeLadder by continent

FacetGrid — annotated KDE plots

It is also possible to add facet specific notation to each chart in a grid. In the following example, we add the mean and the standard deviation and a vertical line drawn at the mean (code below).

Life Ladder kernel density estimation based on the continent, annotated with a mean and standard deviation

Draw a vertical mean line and annotation

FacetGrid — heatmap plots

One of my favorite plot types is a heatmap FacetGrid, i.e., a heatmap in every facet of the grid. This type of plot is useful to visualize four dimensions and a metric in one single plot. The code is a bit cumbersome but can be adjusted quickly to your needs. It is noteworthy that this kind of chart requires a relatively large amount of data or proper segmentation as it does not handle missing values very well.

Facet heatmap, visualizing on the outer rows a year range, outer columns the GDP per Capita, on the inner rows the level of perceived corruption and the inner columns the continents. We see that happiness increases towards the top right (i.e., high GDP per Capita and low perceived corruption). The effect of time is not definite, and some continents (Europe and North America) seem to be happier than others (Africa).