Трехмерные
графики, которые мы подробно рассмотрели на прошлом занятии, иногда изображают
в виде линий уровня:
Для этого
используются функции:
- contour() и
contourf() – если данные по осям x, y, z представлены в
виде двумерных массивов;
- tricontour() и
tricontourf() – если данные для x, y, z представлены
одномерными массивами.
Например, если
взять программу из предыдущего занятия, которая рисовала синусоиду:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7, 4))
ax_3d = fig.add_subplot(projection='3d')
x = np.arange(-2*np.pi, 2*np.pi, 0.2)
y = np.arange(-2*np.pi, 2*np.pi, 0.2)
xgrid, ygrid = np.meshgrid(x, y)
zgrid = np.sin(xgrid) * np.sin(ygrid) / (xgrid * ygrid)
ax_3d.plot_surface(xgrid, ygrid, zgrid)
Но вместо функции
plot_surface() записать функцию
contour() или contourf(), то получим
следующий результат:
ax_3d.contour(xgrid, ygrid, zgrid)
Или, те же самые
функции можно применить для формирования двумерного графика. Вначале создадим
двумерную систему координат:
fig, ax = plt.subplots(1, 2)
а, затем,
вызовем эти же функции, используя переменную ax:
ax[0].contour(xgrid, ygrid, zgrid)
ax[1].contourf(xgrid, ygrid, zgrid)
В обоих
вариантах видим двумерную синусоиду, представленную линиями уровней.
Функции contour()
и contourf() возвращают объект класса QuadContourSet (это дочерний класс от базового
ContourSet). Так вот, имея ссылку на экземпляр этого класса, можно осуществлять
дополнительные манипуляции при отображении графика. Например, добавим к каждой
линии ее числовое значение. Для этого, вначале сохраним ссылку на объект класса
QuadContourSet:
c1 = ax[0].contour(xgrid, ygrid, zgrid)
А, затем,
передадим ее функции clabel():
В результате, на
первом графике появятся подписи:
Того же
результата можно достичь, вызвав метод clabel()
непосредственно через переменную c1:
Подробное
описание этого метода можно посмотреть по ссылке:
https://matplotlib.org/stable/api/contour_api.html#matplotlib.contour.ContourLabeler.clabel
Четвертым
параметром в функциях contour() и contourf() можно
указывать либо число линий уровня:
fig, ax = plt.subplots()
x = np.arange(-2*np.pi, 2*np.pi, 0.2)
y = np.arange(-2*np.pi, 2*np.pi, 0.2)
xgrid, ygrid = np.meshgrid(x, y)
zgrid = np.sin(xgrid) * np.sin(ygrid) / (xgrid * ygrid)
c1 = ax.contour(xgrid, ygrid, zgrid, 15)
c1.clabel()
plt.show()
Либо передавать
список уровней, которые мы бы хотели отобразить для заданного графика:
c1 = ax.contour(xgrid, ygrid, zgrid, [-0.5, -0.2, 0, 0.2, 0.5])
Далее, для линий
уровня можно прописать необходимые цвета, либо через параметр colors:
c1 = ax.contour(xgrid, ygrid, zgrid, colors='g')
либо через список:
c1 = ax.contour(xgrid, ygrid, zgrid, colors=['g', 'b', 'r'])
А также с
помощью цветовых карт, используя параметр cmap:
c1 = ax.contour(xgrid, ygrid, zgrid, cmap='plasma')
Для надписей цвета
можно задавать отдельно в функции clabel():
Теперь все
подписи отображаются черным цветом. Еще один полезный параметр fmt этой функции
позволяет задавать формат отображаемых чисел. Например, так:
c1.clabel(colors='k', fmt='%.2f')
Функции tricontour() и tricontourf()
Похожим образом
работают и функции tricontour() и tricontourf(), только на входе они принимают
одномерные векторы координат x, y, z. Причем,
координаты x, y можно сформировать
совершенно случайным образом, например, так:
x = np.random.rand(100) * 4*np.pi - 2*np.pi
y = np.random.rand(100) * 4*np.pi - 2*np.pi
Здесь мы имеем
по 100 случайных значений в диапазоне [-2π; 2π]. То есть, сетка в
плоскости xy уже не
регулярная, а произвольная. Затем, для этих чисел вычисляется 100 значений
функции синуса:
z = np.sin(x) * np.sin(y) / (1+np.abs(x * y))
И с помощью
функции tricontour() отображается
график с линиями уровня:
c1 = ax.tricontour(x, y, z, cmap='plasma')
c1.clabel(colors='k', fmt='%.2f')
Похожий
результат достигается второй функцией tricontourf():
c1 = ax.tricontourf(x, y, z, cmap='plasma')
Вот так,
довольно просто, можно строить график с линями уровней, используя четыре
функции:
contour(),
contourf() и
tricontour(), tricontourf()
Конечно, это не
все возможности пакета matplotlib по отображению таких графиков.
Более детальную информацию, как всегда, можно посмотреть в документации.