Tommy Lees
Tommy Lees

Reputation: 1373

Create a table of multiple mini barplots in Python

I am trying to reproduce the table of barplots (created below in tableau) in Python.

The Plot that I am trying to recreate in Python

I am struggling to figure out how to do it python (matplotlib, seaborn, pandas).

Here is some example data that illustrates the problem:

import pandas as pd
import numpy as np

data = dict(
    correlation=np.random.normal(0, 0.5, 100),
    pvalue=np.random.normal(0.05, 0.02, 100),
    variable=np.tile(np.array([f"variable{i}" for i in range(10)]), 10),
    model=np.repeat(np.array([f"model{i}" for i in range(10)]), 10)
)
data = pd.DataFrame(data)
data["significant"] = data["pvalue"] < 0.05
data["positive"] = data["correlation"] > 0

My attempted plot for ONE MODEL ("model1") illustrates roughly what I am looking for. As I said I am trying to reproduce the table of barplots (shown above), which would display the results for all of the models.

example_plot_data = data.loc[data.model == "model1"]
example_plot_data.plot(
    kind="bar", x="variable", y="correlation",
    color=example_plot_data.positive.map({True: "b", False: "r"}),
    rot=70,
)
plt.show()

An example plot from Pandas for ONE MODEL

Ideally these are the aesthetics I am looking for

# Aesthetics for the plots:
columns = data["model"]
rows = data["variable"]
bar_size = data["correlation"]        # ideally centred on zero
bar_color = data["correlation"]       # ideally centred on zero (RdBu)
bar_significance = data["significant"]

Upvotes: 1

Views: 531

Answers (1)

Diziet Asahi
Diziet Asahi

Reputation: 40737

In essence, what you are trying to do can be easily done using seaborn's catplot:

sns.catplot(data=data, x='correlation', y='variable', col='model', kind='bar', height=4, aspect=0.3)

enter image description here

If you want to match the aesthetics from your example, you can improve on catplot by using FacetGrid directly, and using a custom function for drawing the bar plot according to the colormap that you want:

from matplotlib.colors import TwoSlopeNorm
from matplotlib.cm import ScalarMappable

norm = TwoSlopeNorm(vcenter=0, vmin=-1, vmax=1)
cmap = plt.get_cmap('bwr')

def my_bar_plot(x, y, **kwargs):
    plt.barh(y=y, width=np.abs(x), color=cmap(norm(x)))

g = sns.FacetGrid(data=data, col='model', height=5, aspect=0.2, sharex=True, sharey=True)
g.map(my_bar_plot, 'correlation', 'variable')
g.set_titles(col_template="{col_name}")
g.fig.colorbar(ScalarMappable(norm=norm, cmap=cmap), orientation='horizontal', ax=g.axes, fraction=0.05)

enter image description here

Refer to the documentation of FacetGrid and the numerous posts here on SO on how to tweak the aspect of the plot even further.

Upvotes: 4

Related Questions