pythonmatplotlibseabornkdeplot

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


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?


Solution

  • 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)