Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seaborn: how to draw a vertical line that matches a specific y value in a cumulative KDE?

I'm using Seaborn to plot a cumulative distribution and it's KDE using this code:

sns.distplot(values, bins=20, 
             hist_kws= {'cumulative': True}, 
             kde_kws= {'cumulative': True} )

This gives me the following chart:

Cumulative distribution and kde

I'd like to plot a vertical line and the corresponding x index where y is 0.8. Something like:

KDE with vertical line

How do I get the x value of a specific y?

like image 874
neves Avatar asked Dec 11 '25 07:12

neves


2 Answers

Update for newer Seaborn versions, with sns.histplot

The code below has been tested with Seaborn 0.13.2. The 0.8 quantile is calculated and shown as an annotated vertical line.

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

values = np.random.normal(1, 20, 1000)
ax = sns.histplot(values, bins=20, cumulative=True, kde=True, color='salmon')
perc = 80
x80 = np.quantile(values, perc / 100)
ax.axvline(x80, color='b')
ax.text(x80, 0.98, f"{perc}th percentile: \nx={x80:.2f} ", color='b',
        ha='right', va='top', transform=ax.get_xaxis_transform())
ax.margins(x=0)
plt.show()

cumulative sns.histplot with 80th percentile

Old answer

You could draw a vertical line at the 80% quantile:

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

values = np.random.normal(1, 20, 1000)
sns.distplot(values, bins=20,
             hist_kws= {'cumulative': True},
             kde_kws= {'cumulative': True} )
plt.axvline(np.quantile(values, 0.8), color='r')
plt.show()

example plot

like image 64
JohanC Avatar answered Dec 13 '25 02:12

JohanC


The answer by @JohanC is probably the best. I went an other route and it's maybe a slightly more generic solution.

The idea is to get the coordinates of the kde line, then find the indice of the point where it crosses the threshold value

values = np.random.normal(size=(100,))
fig = plt.figure()
ax = sns.distplot(values, bins=20, 
             hist_kws= {'cumulative': True}, 
             kde_kws= {'cumulative': True} )

x,y = ax.lines[0].get_data()
thresh = 0.8
idx = np.where(np.diff(np.sign(y-thresh)))[0]
x_val = x[idx[0]]
ax.axvline(x_val, color='red')

enter image description here

like image 35
Diziet Asahi Avatar answered Dec 13 '25 01:12

Diziet Asahi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!