Marginal Distribution Plots in Python

How to add marginal distribution plots.


New to Plotly?

Plotly is a free and open-source graphing library for Python. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

Overview

Marginal distribution plots are small subplots above or to the right of a main plot, which show the distribution of data along only one dimension. Marginal distribution plot capabilities are built into various Plotly Express functions such as scatter and histogram. Plotly Express is the easy-to-use, high-level interface to Plotly, which operates on a variety of types of data and produces easy-to-style figures.

Scatter Plot Marginals

The marginal_x and marginal_y arguments accept one of "histogram", "rug", "box", or "violin" (see also how to create histograms, box plots and violin plots as the main figure).

Marginal plots are linked to the main plot: try zooming or panning on the main plot.

Marginal plots also support hover, including per-point hover as with the rug-plot on the right: try hovering over the points on the right marginal plot.

In [1]:
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_length", y="sepal_width", marginal_x="histogram", marginal_y="rug")
fig.show()
In [2]:
import plotly.express as px
df = px.data.iris()
fig = px.density_heatmap(df, x="sepal_length", y="sepal_width", marginal_x="box", marginal_y="violin")
fig.show()

Marginal Plots and Color

Marginal plots respect the color argument as well, and are linked to the respective legend elements. Try clicking on the legend items.

In [3]:
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_length", y="sepal_width", color="species", 
                 marginal_x="box", marginal_y="violin",
                  title="Click on the legend items!")
fig.show()

Marginal Plots on Histograms

Histograms are often used to show the distribution of a variable, and they also support marginal plots in Plotly Express, with the marginal argument:

In [4]:
import plotly.express as px
df = px.data.iris()
fig = px.histogram(df, x="sepal_length", color="species", marginal="box")
fig.show()

Try hovering over the rug plot points to identify individual country values in the histogram below:

In [5]:
import plotly.express as px
df = px.data.gapminder().query("year == 2007")
fig = px.histogram(df, x="lifeExp", color="continent", marginal="rug", hover_name="country",
                  title="Hover over the rug plot!")
fig.show()

Marginal Plots and Facets

Marginal plots can be used in conjunction with Plotly Express facets so long as they go along different directions:

In [6]:
import plotly.express as px
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", color="sex", facet_col="day",
                  marginal_x="box")
fig.show()
In [7]:
import plotly.express as px
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", color="sex", facet_row="time",
                  marginal_y="box")
fig.show()
In [8]:
import plotly.express as px
df = px.data.tips()
fig = px.histogram(df, x="total_bill", y="tip", color="sex", facet_col="day",
                  marginal="box")
fig.show()

What About Dash?

Dash is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.

Learn about how to install Dash at https://dash.plot.ly/installation.

Everywhere in this page that you see fig.show(), you can display the same figure in a Dash application by passing it to the figure argument of the Graph component from the built-in dash_core_components package like this:

import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure() # or any Plotly Express function e.g. px.bar(...)
# fig.add_trace( ... )
# fig.update_layout( ... )

from dash import Dash, dcc, html

app = Dash()
app.layout = html.Div([
    dcc.Graph(figure=fig)
])

app.run_server(debug=True, use_reloader=False)  # Turn off reloader if inside Jupyter