How to get the full width at half maximum (FWHM) from kdeplot

Question:

I have used seaborn’s kdeplot on some data.

import seaborn as sns
import numpy as np
sns.kdeplot(np.random.rand(100))

Is it possible to return the fwhm from the curve created?
And if not, is there another way to calculate it?

Asked By: Chris U

||

Answers:

I don’t believe there’s a way to return the fwhm from the random dataplot without writing the code to calculate it.

Take into account some example data:

import numpy as np

arr_x = np.linspace(norm.ppf(0.00001), norm.ppf(0.99999), 10000)
arr_y = norm.pdf(arr_x)

Find the minimum and maximum points and calculate difference.

difference = max(arr_y) - min(arr_y)

Find the half max (in this case it is half min)

HM = difference / 2

Find the nearest data point to HM:

nearest = (np.abs(arr_y - HM)).argmin()

Calculate the distance between nearest and min to get the HWHM, then mult by 2 to get the FWHM.

Answered By: invokePrejudice

You can extract the generated kde curve from the ax. Then get the maximum y value and search the x positions nearest to the half max:

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

ax = sns.kdeplot(np.random.rand(100))
kde_curve = ax.lines[0]
x = kde_curve.get_xdata()
y = kde_curve.get_ydata()
halfmax = y.max() / 2
maxpos = y.argmax()
leftpos = (np.abs(y[:maxpos] - halfmax)).argmin()
rightpos = (np.abs(y[maxpos:] - halfmax)).argmin() + maxpos
fullwidthathalfmax = x[rightpos] - x[leftpos]
ax.hlines(halfmax, x[leftpos], x[rightpos], color='crimson', ls=':')
ax.text(x[maxpos], halfmax, f'{fullwidthathalfmax:.3f}n', color='crimson', ha='center', va='center')
ax.set_ylim(ymin=0)
plt.show()

example plot

Note that you can also calculate a kde curve from scipy.stats.gaussian_kde if you don’t need the plotted version. In that case, the code could look like:

import numpy as np
from scipy.stats import gaussian_kde

data = np.random.rand(100)
kde = gaussian_kde(data)
x = np.linspace(data.min(), data.max(), 1000)
y = kde(x)
halfmax = y.max() / 2
maxpos = y.argmax()
leftpos = (np.abs(y[:maxpos] - halfmax)).argmin()
rightpos = (np.abs(y[maxpos:] - halfmax)).argmin() + maxpos
fullwidthathalfmax = x[rightpos] - x[leftpos]
print(fullwidthathalfmax)
Answered By: JohanC
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.