matplotlib 如何创建一个图来可视化68-95-99.7规则?

mo49yndu  于 2023-02-19  发布在  其他
关注(0)|答案(1)|浏览(229)

我创建了一个正态分布图,如下所示:

  1. fig, ax = plt.subplots()
  2. ax.set_title('Плотнось распределения вероятности')
  3. ax.set_xlabel('x')
  4. ax.set_ylabel('f(x)')
  5. x = np.linspace(148, 200, 100) # X от 148 до 200
  6. y = (1 / (5 * math.sqrt(2*math.pi))) * np.exp((-(x-178)**2) / (2*5**2))
  7. ax.plot(x, y)
  8. plt.show()

但我还需要在图形区域内添加垂直线,给内部线段着色,并添加标记,如在picture on axis = 0中。

在python中如何使用matplotlib来实现呢?
我试着使用plt.axvline,但是垂直线超出了我的主图:

  1. plt.axvline(x = 178, color = 'g', label = 'axvline - full height')
  2. plt.axvline(x = 178+5, color = 'b', label = 'axvline - full height')
  3. plt.axvline(x = 178-5, color = 'b', label = 'axvline - full height')
  4. plt.axvline(x = 178+5*2, color = 'r', label = 'axvline - full height')
  5. plt.axvline(x = 178-5*2, color = 'r', label = 'axvline - full height')

bqucvtff

bqucvtff1#

行版本可以使用vlines实现,但请注意,使用fill_between可以更好地再现您的参考图。

线路版本

使用支持yminymax边界的vlines代替axvline
把你的y变成一个lambda f(x, mu, sd)并用它来定义ymax的边界:

  1. # define y as a lambda f(x, mu, sd)
  2. f = lambda x, mu, sd: (1 / (sd * (2*np.pi)**0.5)) * np.exp((-(x-mu)**2) / (2*sd**2))
  3. fig, ax = plt.subplots(figsize=(8, 3))
  4. x = np.linspace(148, 200, 200)
  5. mu = 178
  6. sd = 5
  7. ax.plot(x, f(x, mu, sd))
  8. # define 68/95/99 locations and colors
  9. xs = mu + sd*np.arange(-3, 4)
  10. colors = [*'yrbgbry']
  11. # draw lines at 68/95/99 points from 0 to the curve
  12. ax.vlines(xs, ymin=0, ymax=[f(x, mu, sd) for x in xs], color=colors)
  13. # relabel x ticks
  14. plt.xticks(xs, [f'${n}\sigma$' if n else '0' for n in range(-3, 4)])

阴影版本

使用fill_between可以更好地重新创建示例图形。使用where参数定义着色边界:

  1. fig, ax = plt.subplots(figsize=(8, 3))
  2. x = np.linspace(148, 200, 200)
  3. mu = 178
  4. sd = 5
  5. y = (1 / (sd * (2*np.pi)**0.5)) * np.exp((-(x-mu)**2) / (2*sd**2))
  6. ax.plot(x, y)
  7. # use `where` condition to shade bounded regions
  8. bounds = mu + sd*np.array([-np.inf] + list(range(-3, 4)) + [np.inf])
  9. alphas = [0.1, 0.2, 0.5, 0.8, 0.8, 0.5, 0.2, 0.1]
  10. for left, right, alpha in zip(bounds, bounds[1:], alphas):
  11. ax.fill_between(x, y, where=(x >= left) & (x < right), color='b', alpha=alpha)
  12. # relabel x ticks
  13. plt.xticks(bounds[1:-1], [f'${n}\sigma$' if n else '0' for n in range(-3, 4)])

要标记区域百分比,请在有边界区域的中点处添加text对象:

  1. midpoints = mu + sd*np.arange(-3.5, 4)
  2. percents = [0.1, 2.1, 13.6, 34.1, 34.1, 13.6, 2.1, 0.1]
  3. colors = [*'kkwwwwkk']
  4. for m, p, c in zip(
  5. midpoints, # midpoints of bounded regions
  6. percents, # percents captured by bounded regions
  7. colors, # colors of text labels
  8. ):
  9. ax.text(m, 0.01, f'{p}%', color=c, ha='center', va='bottom')

展开查看全部

相关问题