Issue
I'm trying to plot a several histograms with plt.subplots()
like this:
chart_len = 15
chart_height = 25
fig, axs = plt.subplots(len(weight_classes),figsize=(chart_len,chart_height))
sns.set_theme(style="darkgrid",font_scale=2.5)
colors = sns.color_palette('GnBu_d',len(weight_classes)+1)
for i, wc in enumerate(activity_wc):
data = activity_wc[wc]
bins = [i for i in range(0,data['total_strikes_attempted'].max(),5)]
sns.histplot(data,x='total_strikes_attempted', bins=bins, ax=axs[i], kde=True, stat='probability', color=colors[-(i+2)])
This retrieves this image: histogram subplots
What I'd like though would be for the bars to use the palette, so they would change colors horizontally. Does anyone know how to do this?
Solution
You ax.containers[0]
contains all the histogram bars. You can loop through them and set individual colors. The norm (mapping the x-values to the range 0-1) can be based on the first and last bin boundaries.
Basically, the code would look like:
ax = sns.histplot(...)
norm = plt.Normalize(bins[0], bins[-1])
cmap = sns.color_palette('GnBu_d', as_cmap=True) # use 'GnBu_r_d' for the reversed map
for bar in ax.containers[0]:
bar.set_color(cmap(norm(bar.get_x())))
Supposing activity_wc
is the result of activity.groupby('weight_class')
, the plot can be obtained more directly from the original dataframe. sns.displot
with row='weight_class'
would take care of the grouping and creating a grid of subplots. Note that the figsize
would be controlled by height=
with the height of an individual subplot, and aspect=
with the aspect ratio of one subplot (width divided by height).
Here is an example starting from dummy data. Note that the bins are starting just smaller than zero to avoid rounding errors, and that one bin edge is added to make sure the highest value falls into the last bin. (Use sns.displot(..., facet_kws={'sharex':False})
to have x-tick labels for each subplot.)
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
weight_classes = ['Flyweight', 'Bantamweight', 'Featherweight', 'Lightweight', 'Welterweight',
'Middleweight', 'Light Heavyweight', 'Heavyweight']
activity = pd.DataFrame({'weight_class': np.random.choice(weight_classes, 1000),
'total_strikes_attempted': np.concatenate([np.random.binomial(120, p, 100)
for p in np.linspace(0.2, 0.9, 10)])})
sns.set_theme(style="darkgrid", font_scale=0.8)
bins = np.arange(-0.00001, max(activity['total_strikes_attempted']) + 5, 5)
g = sns.displot(data=activity, x='total_strikes_attempted',
row='weight_class', row_order=weight_classes,
kind='hist', stat='probability', kde=True, palette='GnBu_d',
height=1.6, aspect=3)
norm = plt.Normalize(bins[0], bins[-1])
cmap = sns.color_palette('GnBu_d', as_cmap=True) # use 'GnBu_r_d' for the reversed map
for ax in g.axes.flat:
ax.margins(x=0) # less white space left and right
for bar in ax.containers[0]:
bar.set_color(cmap(norm(bar.get_x())))
plt.tight_layout()
plt.show()
Answered By - JohanC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.