I am using the FacetGrid example from seaborn [Overlapping densities ('ridge plot')]. However, instead of normalizing the integral of the kdeplot, I want to normalize the heights. Does anyone have an idea, how to realize it?
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})
# Create the data
rs = np.random.RandomState(1979)
x = rs.randn(500)
g = np.tile(list("ABCDEFGHIJ"), 50)
df = pd.DataFrame(dict(x=x, g=g))
m = df.g.map(ord)
df["x"] += m
# Initialize the FacetGrid object
pal = sns.cubehelix_palette(10, rot=-.25, light=.7)
g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal)
# Draw the densities in a few steps
g.map(sns.kdeplot, "x",
bw_adjust=.5, clip_on=False,
fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "x", clip_on=False, color="w", lw=2, bw_adjust=.5)
# passing color=None to refline() uses the hue mapping
g.refline(y=0, linewidth=2, linestyle="-", color=None, clip_on=False)
# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
ax = plt.gca()
ax.text(0, .2, label, fontweight="bold", color=color,
ha="left", va="center", transform=ax.transAxes)
g.map(label, "x")
# Set the subplots to overlap
g.figure.subplots_adjust(hspace=-.25)
# Remove axes details that don't play well with overlap
g.set_titles("")
g.set(yticks=[], ylabel="")
g.despine(bottom=True, left=True)
So far, I have done some search engine requests where I tried to find something comparable that has been performed for histplot from matplotlib. However, I have found only solutions for the normalization of the integral.
For just one kdeplot
-
A method normalize()
to normalize the values -
def normalize(arr, t_min, t_max):
norm_arr = []
diff = t_max - t_min
diff_arr = max(arr) - min(arr)
for i in arr:
temp = (((i - min(arr))*diff)/diff_arr) + t_min
norm_arr.append(temp)
return norm_arr
If fill=False
tips = sns.load_dataset("tips")
ax = sns.kdeplot(data=tips, x="total_bill")
line = ax.lines[0]
line.set_ydata(normalize(line.get_ydata(),0,1))
ax.set_ylim(0,1.05)
ax.autoscale_view()
If fill=True
tips = sns.load_dataset("tips")
ax = sns.kdeplot(data=tips, x="total_bill",fill=True)
path = ax.collections[0].get_paths()
ys = normalize(path[0].vertices[:, 1],0,1)
path[0].vertices[:, 1] = ys
ax.set_ylim(0,1.05)
ax.autoscale_view()
Now if you want to use a FacetGrid
then, probably all your problems can be solved just by using sharey=True
like -
g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal, sharey=True)
But still if you need to normalize then-
define a wrapper function -
def kdeplot(data, **kwargs):
ax = sns.kdeplot(data, **kwargs)
if 'fill' in kwargs.keys() and kwargs['fill']==True:
path = ax.collections[0].get_paths()
ys = normalize(path[0].vertices[:, 1],0,1)
path[0].vertices[:, 1] = ys
else:
line = ax.lines[0]
line.set_ydata(normalize(line.get_ydata(),0,1))
ax.set_ylim(0,1.05)
ax.autoscale_view()
then -
tips = sns.load_dataset("tips")
ax = kdeplot(data=tips, x="total_bill",fill=True)
ax = kdeplot(data=tips, x="total_bill",fill=False, lw=4)
Now you can just use kdeplot
instead of sns.kdeplot
-
g.map(kdeplot, "x",bw_adjust=.5, clip_on=False,
fill=True, alpha=1, linewidth=1.5)
g.map(kdeplot, "x", clip_on=False, color="w", lw=2, bw_adjust=.5)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.