这种 plt.fill_between() 方法可以在循环中修改吗?
Can this plt.fill_between() approach be modified in a loop?
我正在尝试在绘图的特定区域中遮蔽 (x,y) 区域。作为一个简化的例子,考虑 confidence intervals 的正态分布。我想遮蔽置信区间,使一个标准差(或一个西格玛)内的区域最暗,两个标准差(或 2 个西格玛)内的区域更亮,等等。我有办法做到这一点,但我正在努力使我的脚本更加灵活。代码如下。
## imports
import numpy as np
import matplotlib.pyplot as plt
from math import pi
## y = f(x)
def get_f(x, mu, sigma):
""" Normal Distribution Probability Density Function """
norm_constant = (sigma* (2*pi)**(1/2))
return [norm_constant * np.exp((-1) * (x[idx] - mu)**2 / (2* sigma**2)) for idx in range(len(x))]
x = np.linspace(0, 100, 5000)
现在我们有了 x 和函数 f(x),我们可以画图了。我留下了有效的代码部分,并注释掉了我对解决方案的尝试。如果我的解决方法有效,我会更喜欢它,因为根据所需间隔的数量进行着色更方便,而且代码不那么重复。
## generate plot
def get_plot(x, num_intervals=None, line_color='g', shade_color='b', mu=48, sigma=7):
""" Returns (x,y) plot; confidence intervals shading is optional """
y = get_f(x, mu, sigma)
plt.plot(x, y, line_color)
if num_intervals is not None:
## THIS CODE SEGMENT BELOW WORKS BUT I WOULD LIKE TO MAKE IT BETTER
plt.fill_between(x, y, where=(mu - sigma <= x), alpha=0.18, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + sigma), alpha=0.18, color=shade_color)
plt.fill_between(x, y, where=(mu - 2*sigma <= x), alpha=0.11, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + 2*sigma), alpha=0.11, color=shade_color)
plt.fill_between(x, y, where=(mu - 3*sigma <= x), alpha=0.02, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + 3*sigma), alpha=0.02, color=shade_color)
## THIS CODE SEGMENT BELOW DOES NOT WORK AS I WOULD LIKE
## IT WILL SHADE THE REGIONS IN THE WRONG SHADE/DARKNESS
## choose shading level via dictionary
# alpha_keys = [idx+1 for idx in range(num_intervals)]
# alpha_vals = [0.18, 0.11, 0.02]
# alpha_dict = dict(zip(alpha_keys, alpha_vals))
# for idx in range(num_intervals):
# print("\nidx & stdev = %d & %d, \nmu - (stdev * sigma) = %.2f, \nmu + (stdev * sigma) = %.2f, alpha = %.2f" %(idx, stdev, mu - stdev*sigma, mu + stdev*sigma, alpha_dict[stdev]), "\n")
# stdev = idx + 1 ## number of standard deviations away from mu
# plt.fill_between(x, y, where=(mu - stdev * sigma <= x), alpha=alpha_dict[stdev], color=shade_color)
# plt.fill_between(x, y, where=(x >= mu + stdev * sigma), alpha=alpha_dict[stdev], color=shade_color)
plt.show()
运行 正确的代码生成 this plot. My attempt at a more convenient solution produces this plot 并生成以下输出(通过 print 语句),但我找不到错误的根源。
idx & stdev = 0 & 1,
mu - (stdev * sigma) = 41.00,
mu + (stdev * sigma) = 55.00, alpha = 0.18
idx & stdev = 1 & 2,
mu - (stdev * sigma) = 34.00,
mu + (stdev * sigma) = 62.00, alpha = 0.11
idx & stdev = 2 & 3,
mu - (stdev * sigma) = 27.00,
mu + (stdev * sigma) = 69.00, alpha = 0.02
我的方法更方便的解决方案是否适用?
在这里,我提供了比您的更紧凑的正态分布图版本。我使用 Scipy 包中的正态分布函数,而不是重新发明轮子。
from scipy.stats import norm # import normal dist.
import matplotlib.pyplot as plt
import numpy as np
# mean and standard deviation
mu,sigma = 48,7
# normal_dist(mu,sigma)
anorm = norm(loc=mu, scale=sigma)
factors = [1,2,3] # multiple of sigma
alphas = [0.18, 0.11, 0.08] # level of alpha
fig, ax = plt.subplots(1, 1)
fig.set_size_inches(10,8)
# plot full normal curve
segs = 100
x = np.linspace(anorm.ppf(0.0005), anorm.ppf(0.9995), segs)
ax.plot(x, anorm.pdf(x), 'b-', lw=0.5, alpha=0.6)
# plot color-filled portions
for fac, alp in zip(factors, alphas):
# print(mu-fac*sigma, mu+fac*sigma, alp)
lo = mu-fac*sigma
hi = mu+fac*sigma
xs = np.linspace(lo, hi, fac*segs/4) # prep array of x's
plt.fill_between(xs, anorm.pdf(xs), y2=0, where= xs >= lo , \
interpolate=False, \
color='blue', alpha=alp)
plt.ylim(0, 0.06)
plt.show()
结果图:
我正在尝试在绘图的特定区域中遮蔽 (x,y) 区域。作为一个简化的例子,考虑 confidence intervals 的正态分布。我想遮蔽置信区间,使一个标准差(或一个西格玛)内的区域最暗,两个标准差(或 2 个西格玛)内的区域更亮,等等。我有办法做到这一点,但我正在努力使我的脚本更加灵活。代码如下。
## imports
import numpy as np
import matplotlib.pyplot as plt
from math import pi
## y = f(x)
def get_f(x, mu, sigma):
""" Normal Distribution Probability Density Function """
norm_constant = (sigma* (2*pi)**(1/2))
return [norm_constant * np.exp((-1) * (x[idx] - mu)**2 / (2* sigma**2)) for idx in range(len(x))]
x = np.linspace(0, 100, 5000)
现在我们有了 x 和函数 f(x),我们可以画图了。我留下了有效的代码部分,并注释掉了我对解决方案的尝试。如果我的解决方法有效,我会更喜欢它,因为根据所需间隔的数量进行着色更方便,而且代码不那么重复。
## generate plot
def get_plot(x, num_intervals=None, line_color='g', shade_color='b', mu=48, sigma=7):
""" Returns (x,y) plot; confidence intervals shading is optional """
y = get_f(x, mu, sigma)
plt.plot(x, y, line_color)
if num_intervals is not None:
## THIS CODE SEGMENT BELOW WORKS BUT I WOULD LIKE TO MAKE IT BETTER
plt.fill_between(x, y, where=(mu - sigma <= x), alpha=0.18, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + sigma), alpha=0.18, color=shade_color)
plt.fill_between(x, y, where=(mu - 2*sigma <= x), alpha=0.11, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + 2*sigma), alpha=0.11, color=shade_color)
plt.fill_between(x, y, where=(mu - 3*sigma <= x), alpha=0.02, color=shade_color)
plt.fill_between(x, y, where=(x <= mu + 3*sigma), alpha=0.02, color=shade_color)
## THIS CODE SEGMENT BELOW DOES NOT WORK AS I WOULD LIKE
## IT WILL SHADE THE REGIONS IN THE WRONG SHADE/DARKNESS
## choose shading level via dictionary
# alpha_keys = [idx+1 for idx in range(num_intervals)]
# alpha_vals = [0.18, 0.11, 0.02]
# alpha_dict = dict(zip(alpha_keys, alpha_vals))
# for idx in range(num_intervals):
# print("\nidx & stdev = %d & %d, \nmu - (stdev * sigma) = %.2f, \nmu + (stdev * sigma) = %.2f, alpha = %.2f" %(idx, stdev, mu - stdev*sigma, mu + stdev*sigma, alpha_dict[stdev]), "\n")
# stdev = idx + 1 ## number of standard deviations away from mu
# plt.fill_between(x, y, where=(mu - stdev * sigma <= x), alpha=alpha_dict[stdev], color=shade_color)
# plt.fill_between(x, y, where=(x >= mu + stdev * sigma), alpha=alpha_dict[stdev], color=shade_color)
plt.show()
运行 正确的代码生成 this plot. My attempt at a more convenient solution produces this plot 并生成以下输出(通过 print 语句),但我找不到错误的根源。
idx & stdev = 0 & 1,
mu - (stdev * sigma) = 41.00,
mu + (stdev * sigma) = 55.00, alpha = 0.18
idx & stdev = 1 & 2,
mu - (stdev * sigma) = 34.00,
mu + (stdev * sigma) = 62.00, alpha = 0.11
idx & stdev = 2 & 3,
mu - (stdev * sigma) = 27.00,
mu + (stdev * sigma) = 69.00, alpha = 0.02
我的方法更方便的解决方案是否适用?
在这里,我提供了比您的更紧凑的正态分布图版本。我使用 Scipy 包中的正态分布函数,而不是重新发明轮子。
from scipy.stats import norm # import normal dist.
import matplotlib.pyplot as plt
import numpy as np
# mean and standard deviation
mu,sigma = 48,7
# normal_dist(mu,sigma)
anorm = norm(loc=mu, scale=sigma)
factors = [1,2,3] # multiple of sigma
alphas = [0.18, 0.11, 0.08] # level of alpha
fig, ax = plt.subplots(1, 1)
fig.set_size_inches(10,8)
# plot full normal curve
segs = 100
x = np.linspace(anorm.ppf(0.0005), anorm.ppf(0.9995), segs)
ax.plot(x, anorm.pdf(x), 'b-', lw=0.5, alpha=0.6)
# plot color-filled portions
for fac, alp in zip(factors, alphas):
# print(mu-fac*sigma, mu+fac*sigma, alp)
lo = mu-fac*sigma
hi = mu+fac*sigma
xs = np.linspace(lo, hi, fac*segs/4) # prep array of x's
plt.fill_between(xs, anorm.pdf(xs), y2=0, where= xs >= lo , \
interpolate=False, \
color='blue', alpha=alp)
plt.ylim(0, 0.06)
plt.show()
结果图: