seabornkernel-densitykdeplotdisplot

seaborn kdeplot: make ymax equals density max for different hues


I plotted:

enter image description here

with this code example:

# plot
plt.close()

g = sns.JointGrid(x="alntmscore", y="hit_count", data=foldseek_df_groupby)


# scatter plot
sns.scatterplot(x = 'alntmscore', y = 'hit_count', data =  foldseek_df_groupby_sim, color="blue",  alpha=0.5, s=0.5, ax=g.ax_joint)
sns.scatterplot(x = 'alntmscore', y = 'hit_count', data =  foldseek_df_groupby_dissim, color="red", alpha=0.5, s=0.5, ax=g.ax_joint)


# 2D dist (i.e. the graph)
linewidths = 1
levels = 8
thresh = 0.1

sns.kdeplot(
    x = foldseek_df_groupby_dissim['alntmscore'], y = foldseek_df_groupby_dissim['hit_count'], cmap="Reds",
    shade=False, shade_lowest=False, ax=g.ax_joint, common_norm=False,
    linestyles='-', linewidths=linewidths, levels=levels, thresh=thresh,
)

sns.kdeplot(
    x = foldseek_df_groupby_sim['alntmscore'], y = foldseek_df_groupby_sim['hit_count'], cmap="Blues",
    shade=False, shade_lowest=False, ax=g.ax_joint, common_norm=False,
    linestyles='-', linewidths=linewidths, levels=levels, thresh=thresh,
)

# 1D dist (i.e. the axes)
sns.kdeplot(
    foldseek_df_groupby_sim['alntmscore'],  color="blue", common_norm=False,
    linestyle='-', ax=g.ax_marg_x
)

sns.kdeplot(
    foldseek_df_groupby_dissim['alntmscore'],  color="red", common_norm=False,
    linestyle='-', ax=g.ax_marg_x
)

sns.kdeplot(
    foldseek_df_groupby_sim['hit_count'],  color="blue", common_norm=False,
    linestyle='-',  ax=g.ax_marg_y, vertical=True
)

sns.kdeplot(
    foldseek_df_groupby_dissim['hit_count'],  color="red", common_norm=False,
    linestyle='-', ax=g.ax_marg_y, vertical=True
)

# format
g.fig.set_dpi(1200)                     # dpi
g.fig.set_size_inches((2, 2))           # fig size
g.ax_joint.set_xlabel('TM-score')
g.ax_joint.set_ylabel('hit count')
g.ax_joint.set_title(model_species, pad = 30)
g.ax_joint.yaxis.get_ticklocs(minor=True)
g.ax_joint.minorticks_on()
#g.ax_joint.set_xlim(0,1.0)
#g.ax_joint.set_ylim(0,1000)

plt.show()
#plt.savefig(output_dir + model_species + '_box.png', bbox_inches='tight')
plt.close()

You can see that the red density in the kdeplot at the top (i.e. ax=g.ax_marg_x) is relatively flat but I want to make it more obvious.

Is it possible to make the red density peaks the same height as the blue density?

For example, by assigning two different ymax of the same kdeplot, though which sounds weird to me.


Solution

  • Well, it is possible, but it will look misleading.

    import matplotlib.pyplot as plt
    import seaborn as sns
    
    iris = sns.load_dataset('iris')
    g = sns.jointplot(kind='kde', data=iris, x="petal_length", y="petal_width", hue='species')
    
    # rescale the curves in the x direction
    max_height = max([max(curve.get_ydata()) for curve in g.ax_marg_x.get_lines()])
    for curve in g.ax_marg_x.get_lines():
        height = max(curve.get_ydata())
        curve.set_ydata(curve.get_ydata() / height * max_height)
    
    # rescale the curves in the y direction
    max_height = max([max(curve.get_xdata()) for curve in g.ax_marg_y.get_lines()])
    for curve in g.ax_marg_y.get_lines():
        height = max(curve.get_xdata())
        curve.set_xdata(curve.get_xdata() / height * max_height)
    plt.show()
    

    At the left the original plot, at the right the kde curves are rescaled to the same height. There, sotosa looks much smaller than versicolor and virginia, just because the values occupy a smaller domain.

    sns jointplot kde rescaled