Simd
Simd

Reputation: 21343

How to shade a region under a curve

I would like to shade a region under a curve. This is my attempt:

from scipy.stats import lognorm
import matplotlib.pyplot as plt
import numpy as np
xpoints = np.linspace(0,10,100)
plt.vlines(2, 0, lognorm.pdf(2,1), color='r', linestyles='solid')
plt.vlines(3, 0, lognorm.pdf(3,1), color='r', linestyles='solid')
plt.fill_between([2,3], [lognorm.pdf(2,1), lognorm.pdf(3,1)], color='red')
plt.plot(xpoints, lognorm.pdf(xpoints,1))

However this doesn't shade under the curve properly.

enter image description here

How do you do this properly?

Upvotes: 1

Views: 1159

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339560

Using where

Using the where argument of fill_between allows to select the range over which the filling should occur.

from scipy.stats import lognorm
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = lognorm.pdf(x, 1)

plt.vlines(2, 0, lognorm.pdf(2, 1), color='r', linestyles='solid')
plt.vlines(3, 0, lognorm.pdf(3, 1), color='r', linestyles='solid')

plt.fill_between(x, y, where=((x >= 2) & (x <= 3)), color='red')
plt.plot(x, y)

plt.show()

enter image description here

A problem with this may be that the point of the original curve which is closest to the boundary chosen may still be too far away, such that gaps may occur.

Worthwhile to note that if you choose the points dense enough, or for that matter, just intelligently enough, such problems would be circumvented. I.e. using 101 points, such that 2.0 and 3.0 are actually part of the data,

x = np.linspace(0, 10, 101)

would result in a nice picture:

enter image description here

Plotting a refined version of the curve.

It may hence make sense to reevaluate your function on a denser grid and plot it independently.

from scipy.stats import lognorm
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = lognorm.pdf(x, 1)

plt.vlines(2, 0, lognorm.pdf(2, 1), color='r', linestyles='solid')
plt.vlines(3, 0, lognorm.pdf(3, 1), color='r', linestyles='solid')

xf = np.linspace(2, 3, 301)
yf = lognorm.pdf(xf, 1)
plt.fill_between(xf, yf, color='red')
plt.plot(x, y)

plt.show()

enter image description here

Upvotes: 2

Sohaib Jundi
Sohaib Jundi

Reputation: 1664

you are filling based on 2 points only, try this instead:

plt.fill_between(xpoints[20:31], [lognorm.pdf(i,1) for i in xpoints[20:31]], color='red')

Upvotes: 0

Related Questions