Issue
I am trying my best to combine the following four figures to three plots and show how (a) & (b) differ from (c) & (d) using colors and hatch marks. All four green plots are the same parameter, just grouped accordingly. Same with orange and blue.
Here is how I created each individual plot using the melt
function:
df_CohDmg
Out[13]:
Region Age60 CohDmg value
0 Posterior Age $\leq$ 60 tn 1844.377999
1 Posterior Age $\leq$ 60 tn 654.815766
2 Equator Age $\leq$ 60 tn 287073.028315
3 Equator Age $\leq$ 60 tn 301519.815540
4 Posterior Age $\leq$ 60 tn 838.798937
.. ... ... ... ...
112 Posterior Age $\leq$ 60 tt 11185.849816
113 Equator Age $>$ 60 tt 15345.033316
114 Posterior Age $>$ 60 tt 62.232998
115 Equator Age $>$ 60 tt 490.447922
116 Equator Age $>$ 60 tt 11468.986366
[117 rows x 4 columns]
df_CohDmg = pd.melt(md, id_vars=[R, A60],
value_vars=['tn', 'ts', 'tt'],
var_name='CohDmg')
def CohDmgDistPlot(dataSubset=None, figName=None, hue=None, hue_order=None,
labels=None):
f, ax = plt.subplots()
sns.set_context("paper", rc={"font.size":12, "axes.titlesize":8,
"axes.labelsize":12})
ax = sns.displot(data=dataSubset, hue=hue, hue_order=hue_order,
x='value', kind="kde", fill=True, legend=False, height=5,
aspect=1.6, bw_adjust=1, log_scale=True)
ax.set(xlabel='Cohesive Damage Initiation Parameters [Pa]',
ylabel='Kernel Density Estimation')
if labels != None:
# Legend
plt.legend(labels=labels, loc='best').set_title("Parameter")
# Set limits so all plots are the same scale
ax.set(ylim=(0, 0.3))
ax.set(xlim=(8*10**-1, 4*10**7))
ax.savefig(os.path.join(SF, 'Cohesive_Damage_Initiation_Distribution' +
'{}.pdf'.format(figName)),
bbox_inches='tight')
plt.close(f)
From this function that I defined here is how I am calling each subset of the data:
# Simplify plots
labels = [r'$t_{n}$', r'$t_{s}$', r'$t_{t}$']
hue = 'CohDmg'
hue_order = [Eq, Po]
CohDmgDistPlot(df_CohDmg, figName='', labels=labels, hue=hue)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Po)], figName='_Posterior',
hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Eq)], figName='_Equator',
hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[A60] == Aleq60)], figName='_AgeLeq60',
hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[A60] == Ag60)], figName='_Ageg60',
hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Po) & (df_CohDmg[A60] == Aleq60)],
figName='_Posterior_Leq60', hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Po) & (df_CohDmg[A60] == Ag60)],
figName='_Posterior_g60', hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Eq) & (df_CohDmg[A60] == Aleq60)],
figName='_Equator_Leq60', hue=hue, labels=labels)
CohDmgDistPlot(df_CohDmg[(df_CohDmg[R] == Eq) & (df_CohDmg[A60] == Ag60)],
figName='_Equator_g60', hue=hue, labels=labels)
Ideally, I would use the paired colors to represent (a) & (b) and hatch marks for (b) & (d).
Thank you so much as I have been able to figure this out.
Solution
Here is an example with 3 subplots. Each subplot first gets a kdeplot
for one region, and then a kdeplot
for the other with different colors. Each individual kdeplot
uses hue
to differentiate between the ages. Also, these age groups are stacked instead of being drawn on top of each other. Further, one age group gets a hatching.
Some manipulations are needed to get a proper legend. set_hach
is called both on the legend handles as on the polygon forming the kdeplot
. The stacking first creates the last age group, so the hatching needs to reverse the list.
Many variations are possible, also depending on what you want to show and how much the graphs overlap. For example, a new column could be created combining two columns for the hue
, and they all could be stacked instead of drawn on top of each other.
Also note that kdeplot
has a parameter common_norm
that default to True
and reduces the graph for each hue-group depending on the group's size.
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
regions = ['Posterior', 'Equator']
ages = ['Age $\leq$ 60 ', 'Age $>$ 60 ']
coh_dmgs = ['tn', 'ts', 'tt']
df_CohDmg = pd.DataFrame({'Region': np.random.choice(regions, 200),
'Age60': np.random.choice(ages, 200),
'CohDmg': np.random.choice(coh_dmgs, 200),
'value': np.random.randn(20, 10).cumsum(axis=0).ravel() * 20 + 100})
df_CohDmg.loc[df_CohDmg['Region'] == regions[1], 'value'] += 100
df_CohDmg.loc[df_CohDmg['Age60'] == ages[1], 'value'] += 50
'''
df_CohDmg['Region'] = pd.Categorical(df_CohDmg['Region'], categories=regions)
df_CohDmg['Age60'] = pd.Categorical(df_CohDmg['Age60'], categories=ages)
df_CohDmg['CohDmg'] = pd.Categorical(df_CohDmg['CohDmg'], categories=coh_dmgs)
'''
fig, axs = plt.subplots(ncols=3, figsize=(15, 3), sharex=True, sharey=True)
colors = [plt.cm.tab20.colors[i:i + 2] for i in range(0, len(regions) * 2, 2)]
hatches = ['', '//']
for ax, coh_dmg in zip(axs, coh_dmgs):
handles = []
for region, palette in zip(regions, colors):
sns.kdeplot(data=df_CohDmg[(df_CohDmg['CohDmg'] == coh_dmg) & (df_CohDmg['Region'] == region)],
x='value', hue='Age60', hue_order=ages, multiple='stack', palette=palette, ax=ax)
for h, age, hatch in zip(ax.legend_.legendHandles, ages, hatches):
h.set_label(f'{region}, {age}')
h.set_hatch(hatch)
handles.append(h)
ax.legend_.remove() # remove the automatic legends
ax.set_title(f'CohDmg={coh_dmg}')
for collection, hatch in zip(ax.collections[::-1], hatches * len(regions)):
collection.set_hatch(hatch)
axs[-1].legend(handles=handles, loc='upper left', bbox_to_anchor=[1.01, 1.01])
plt.tight_layout()
plt.show()
Answered By - JohanC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.