2

I would like to shade the area under the kdeplot below the value -1.64.

I drew the kdeplot and a vertical line at -1.64. How do I fill the triangular area between the kdeplot, the x-axis, and the vertical line?

Also, I would like the height of the orange vertical line to just reach the kdeplot.

fig, ax = plt.subplots(nrows=2, ncols=2,figsize=(12,6), tight_layout=True, sharex=True, sharey=True)
sns.kdeplot(pop_norm.fev1_z, ax=ax[0,0], legend=False)
ax[0,0].axvline(x=pop_norm.fev1_z.mean(), linestyle = '--', alpha =0.5)
ax[0,0].axvline(x=-1.64, linestyle = '-', color = palette[1], alpha =0.5)
ax[0,0].set_xlabel("FEV1 z-score")
ax[0,0].set_ylabel("Population density")

sns.kdeplot(pop_norm.fvc_z, ax=ax[0,1], legend=False)
ax[0,1].axvline(x=pop_norm.fvc_z.mean(), linestyle = '--', alpha =0.5)
ax[0,1].axvline(x=-1.64, linestyle = '-', color = palette[1], alpha =0.5)
ax[0,1].set_xlabel("FVC z-score")


sns.kdeplot(pop_norm.fev1fvc_z, ax=ax[1,0], legend=False)
ax[1,0].axvline(x=pop_norm.fev1fvc_z.mean(), linestyle = '--', alpha =0.5)
ax[1,0].axvline(x=-1.64, linestyle = '-', color = palette[1], alpha =0.5)
ax[1,0].set_xlabel("FEV1/FVC z-score")
ax[1,0].set_ylabel("Population density")

sns.kdeplot(pop_norm.fef2575_z, ax=ax[1,1], legend=False)
ax[1,1].axvline(x=pop_norm.fef2575_z.mean(), linestyle = '--', alpha =0.5)
ax[1,1].axvline(x=-1.64, linestyle = '-', color = palette[1], alpha =0.5)
ax[1,1].set_xlabel("FEF 25-75% z-score")

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
jisoo
  • 21
  • 2
  • Hi there, welcome to Stack Overflow! Please read about how to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). According to the wording of your question there is really no need for this whole piece of code, and it might discourage people from helping – Prunus Persica Sep 15 '20 at 14:56

1 Answers1

4

You can extract the curve of the kde by extracting the x and y data from the last lines element in the subplot.

These x and y can be used both to interpolate the curve height at given x values, and as parameters for fill_between().

Here is an example with one subplot:

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

pop_norm_fev1_z = np.random.normal(-.004, .01, 500).cumsum()

fig, ax = plt.subplots(figsize=(12, 6))

sns.kdeplot(pop_norm_fev1_z, ax=ax, legend=False)
x = ax.lines[-1].get_xdata()
y = ax.lines[-1].get_ydata()
mean = pop_norm_fev1_z.mean()
ax.vlines(mean, 0, np.interp(mean, x, y), linestyle='--', alpha=0.5)
x_special = -1.64
ax.vlines(x_special, 0, np.interp(x_special, x, y), linestyle='-', color='crimson', alpha=0.5)
ax.fill_between(x, 0, y, where=x < x_special, color='gold', alpha=0.3)
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66