Я хочу построить кривую нормального распределения и заштриховать три области под кривой, определенной как «среднее» (между отрицательным и положительным стандартным отклонением), «выше или ниже среднего» (между отрицательным и отрицательным, соответственно положительными положительные два стандартных отклонения) и «намного выше или ниже среднего» (между отрицательными тремя и отрицательными двумя соответственно положительными двумя и положительными тремя стандартными отклонениями).
Сначала я искал функцию, которая может обрабатывать раскраску, и наткнулся на метод fill_between
в matplotlib.Затем я использовал np.linspace
для определения трех x-векторов и использовал цикл for и fill_between
для затенения областей.Затем я понял, что fill_between
«соединит» две области, даже если я хочу, чтобы средняя часть была не заштрихована (что относится к «выше и ниже среднего» и «намного выше и ниже среднего»).Так что этот метод не работает.
Затем я наткнулся на аргумент ключевого слова where
в fill_between
и нашел решение, которое использует логические операторы для определения трех областей.Этот метод работает, но я не очень доволен им и чувствую, что должен быть более эффективный способ решить эту проблему?
Вот мой код:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
plotdata = {"mean": 50,"sd": 10}
# plot normal distribution
x_normdist = np.linspace(plotdata["mean"] - 3 * plotdata["sd"], plotdata["mean"] + 3 * plotdata["sd"],1000)
y = norm.pdf(x_normdist,plotdata["mean"],plotdata["sd"])
plt.plot(x_normdist,y)
# create logical lists
average = (x_normdist >= (plotdata["mean"] - 1 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 1 * plotdata["sd"]))
above_and_below_average = (x_normdist >= (plotdata["mean"] - 2 * plotdata["sd"])) & (x_normdist < (plotdata["mean"] - 1 * plotdata["sd"])) | (x_normdist > (plotdata["mean"] + 1 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 2 * plotdata["sd"]))
far_above_and_belowe_average = (x_normdist >= (plotdata["mean"] - 3 * plotdata["sd"])) & (x_normdist < (plotdata["mean"] - 2 * plotdata["sd"])) | (x_normdist > (plotdata["mean"] + 2 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 3 * plotdata["sd"]))
# bind lists
regions = [average,above_and_below_average,far_above_and_belowe_average]
# set alpha values
alpha_values = [0.75,0.5,0.25]
# plot regions with corresponding alpha values
for idx,region in enumerate(regions):
y = norm.pdf(x_normdist, plotdata["mean"], plotdata["sd"])
plt.fill_between(x_normdist, y,color="C0",alpha=alpha_values[idx],where=regions[idx])
plt.show()