5.6. Stackplot - надставленные области

Данный график очень похож на fill_between, но в отличии от него, он может создавать области между несколькими линиями и позволяет определить как эти области должны выравниваться относительно друг-друга.

Несколько примеров

Чтобы построить график, методу stackplot необходимо всего два аргумента: массив с координатами x и массивы c y координатами линий. Вот только отсчет y координат каждой последующей линии ведется от y координат предыдущей линии:

import numpy as np
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]

y1 = [2, 6, 4, 8, 2, 4]
y2 = [2, 4, 2, 4, 4, 10]

#  Фактические координаты y2 = [4, 10, 6, 12, 6, 14]

fig, ax = plt.subplots()

ax.stackplot(x, [y1, y2])

fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot c параметрами внешнего вида по умолчанию

Наличие в данных отрицательных значений может привести к двусмысленности:

import numpy as np
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]

y1 = [2, 6, 4, 8, 2, 4]
y2 = [2, 4, 2, -1, 4, -2]

#  Фактические координаты y2 = [4, 10, 6, 7, 6, 2]

fig, ax = plt.subplots()

ax.stackplot(x, [y1, y2])

fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: наличие отрицательных значений в данных приводит к двусмысленности их отображения

В качестве второго аргумента может выступать массив из массивов y-координат:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(100)
y = np.random.rand(5, 100)*x**(2/3)+x

fig, ax = plt.subplots()

ax.stackplot(x, y)

fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: разные данные могут быть представлены одним двумерным массивом


Выравнивание областей

Выровнять области можно несколькими способами, указав в аргументе baseline одну из следующих строк: 'zero', 'sym', 'wiggle', 'weighted_wiggle'. Если указать способ 'zero', то выравнивание следующей линии будет рассчитано относительно предыдущей (установлено по умолчанию):

import numpy as np
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]

y1 = [2, 6, 4, 8, 2, 4]
y2 = [2, 4, 2, 4, 4, 10]

fig, ax = plt.subplots()

ax.stackplot(x, y1, y2, baseline = 'zero')

ax.set_title('zero baseline')
fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: выравнивание областей методом zero_baseline

Всю область можно выровнять так, что ее края будут симметричны относительно нулевой линии, для этого необходимо указать строку 'sym':

import numpy as np
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]

y1 = [2, 6, 4, 8, 2, 4]
y2 = [2, 4, 2, 4, 4, 10]

fig, ax = plt.subplots()

ax.stackplot(x, y1, y2, baseline = 'sym')
ax.plot(np.zeros(6), color = 'black')

ax.set_title('sym baseline')
fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: выравнивание областей методом sym_baseline

Метод выравнивания 'wiggle' позволяет добиться минимального наклона краев области:

import numpy as np
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4, 5]

y1 = [2, 6, 4, 8, 2, 4]
y2 = [2, 4, 2, 4, 4, 10]

fig, ax = plt.subplots()

ax.stackplot(x, y1, y2, baseline = 'wiggle')

ax.plot(np.zeros(6), color = 'black')

ax.set_title('wiggle baseline')
fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: выравнивание областей методом wiggle_baseline

Последний способ выравнивания - 'weighted_wiggle', так же как и метод расчета 'zero' выравнивает одну линию относительно предыдущей, но смещает саму область пропорционально ширине каждого полученного слоя:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(15)

y1 = np.random.rand(15)
y2 = np.random.rand(15)

fig, ax = plt.subplots()

ax.stackplot(x, y1, y2,
             baseline = 'weighted_wiggle')
ax.plot(np.zeros(15), color = 'black')

ax.set_title('weighted_wiggle baseline')
fig.set_figwidth(12)    #  ширина и
fig.set_figheight(6)    #  высота "Figure"
fig.set_facecolor('floralwhite')
ax.set_facecolor('seashell')

plt.show()

Matplotlib stackplot: выравнивание областей методом weighted_wiggle_baseline

Данный вид графиков очень похож на гистограммы, только в отличии от них, каждая величина пропорциональна не прямоугольнику а слою. А различные методы расчета смещения базовой линии позволяют в различной степени "почувствовать энергию" каждого слоя. Давайте создадим искусственные данные и посмотрим, как они могут выглядеть:

import numpy as np
import matplotlib.pyplot as plt

def gaus_mix(n):
    a = np.zeros(n)
    x = np.random.randint(20, 60, size = 1)
    y = 0.01*np.random.randint(5, 95, size = 1)
    z = 0.3*x
    for i in range(n):
            w = (i / float(n) - y) * z
            a[i] += x * np.exp(-w * w)
    return a

x = np.arange(100)
y = []
for i in range(15):
    y.append(gaus_mix(100))

fig, axes = plt.subplots(4, 1)

axes[0].stackplot(x, y,
             baseline = 'zero')
axes[1].stackplot(x, y,
             baseline = 'sym')
axes[2].stackplot(x, y,
             baseline = 'wiggle')
axes[3].stackplot(x, y,
             baseline = 'weighted_wiggle')

axes[0].set_title('zero baseline')
axes[1].set_title('sym baseline')
axes[2].set_title('wiggle baseline')
axes[3].set_title('weighted_wiggle baseline')

#  Увеличим расстояние между областями Axes:
fig.subplots_adjust(hspace=0.5)

fig.set_figwidth(12)    #  ширина и
fig.set_figheight(12)    #  высота "Figure"

plt.show()

Matplotlib stackplot

Так же, в отличии от гистограмм, данный вид графиков позволяет отлично визуализировать соотношение непрерывных величин на протяженном промежутке времени, например, объемы выпуска автомобилей различными компаниями за последние 40 лет.