рекомендации

пятница, 17 сентября 2021 г.

Визуализация данных с помощью Matplotlib

В мире Python существует несколько инструментов для визуализации данных:
  • matplotlib создает графики полиграфического качества в различных форматах и в интерактивных средах на разных платформах, вы можете создавать графики, гистограммы, спектры мощности, диаграммы ошибок, диаграммы рассеяния и т. д. с помощью всего лишь нескольких строк кода.
  • Seaborn - библиотека для создания привлекательных и информативных статистических графиков на Python.
Другие библиотеки (в частности, pandas также обладает собственной функциональностью визуализации).

Здесь мы будем рассматривать предпочтительно matplotlib. Matplotlib - отличная библиотека 2D и 3D графиков. Среди преимуществ этой библиотеки:

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

Работа с Matplotlib

import matplotlib.pyplot as plt

# This line configures matplotlib to show figures embedded in the notebook,
# instead of opening a new window for each figure. More about that later.

%matplotlib inline
import numpy as np

Чтобы создать простой линейный график matplotlib, вам необходимо задать два массива для координат x и y, и затем вызвать функцию plt.plot ().

pyplot является частью пакета Matplotlib. Его можно импортировать следующим образом:

import matplotlib.pyplot as plt

Давайте начнем с чего-нибудь крутого, а потом перейдем к скучным вещам, не так ли?

Волны

import numpy as np
import matplotlib.pyplot as plt

"""

numpy.arange([start, ]stop, [step, ]dtype=None)
    Return evenly spaced values within a given interval.
    Only stop value is required to be given.
    Default start = 0 and step = 1

"""

x = np.arange(0,5,0.1)
y = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y)
plt.plot(x,y2)
plt.show()


Назад к основам

Гистограммы

Это диаграмма, на которой числовые значения переменных представлены высотой или длиной линий или прямоугольников одинаковой ширины.

objects = ('Python', 'C++', 'Java', 'Perl', 'Scala', 'Lisp')
x_pos = np.arange(len(objects)) # Like the enumerate function.
performance = [10,8,6,4,2,1] # Y values for the plot

# Plots the valueswith x_pos as X axis and Performance as Y axis
plt.bar(x_pos, performance)

# Change X axis values to names from objects
plt.xticks(x_pos, objects)

# Assigns Label to Y axis
plt.ylabel('Usage')

plt.title('Programming Language Usage')
plt.show()


Круговая диаграмма

Круговая диаграмма - это статистическая диаграмма, которая разделена на части, чтобы проиллюстрировать пропорцию между переменными.

import matplotlib.pyplot as plt

# Data to plot
labels = ('Python', 'C++', 'Ruby', 'Java')
sizes = [10,16,14,11]

# Predefined color values
colors = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue']

# Highlights a particular Value in plot
explode = (0.1, 0, 0, 0) # Explode 1st slice

# Plot
plt.pie(sizes, explode=explode, labels=labels, colors=colors)

plt.show()


Линейный график

Уравнение:

t = arange(0.0, 20.0, 1)

определяет начало с 0, строит 20 элементов (длина нашего массива) с шагом 1. Мы будем использовать его, чтобы получить наши значения X для нескольких примеров.

import matplotlib.pyplot as plt

t = np.arange(0.0, 20.0, 1)
s = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
plt.plot(t, s)

plt.xlabel('Item (s)')
plt.ylabel('Value')
plt.title('Python Line Chart')
plt.grid(True)
plt.show()



import matplotlib.pyplot as plt

t = np.arange(0.0, 20.0, 1)
s = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
s2 = [4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
plt.plot(t, s)
plt.plot(t,s2)

plt.xlabel('Item (s)')
plt.ylabel('Value')
plt.title('Python Line Chart')
plt.grid(True)
plt.show()


Хорошо, теперь, когда с этим разобрались, давайте попробуем что-нибудь вроде $y =x^2$

import matplotlib.pyplot as plt

a=[]
b=[]
# Try changing the range values to very small values
# Notice the change in output then
for x in range(-25000,25000):
    y=x**2
    a.append(x)
    b.append(y)

plt.plot(a,b)
plt.show()


Вложенные графики

Matplotlib позволяет добавлять вложенные графики к каждому рисунку с помощью объектно-ориентированного API. Все время мы использовали глобальный экземпляр графика. Мы собираемся изменить это сейчас и сохранить экземпляр в переменной fig. Из нее мы создаем новый экземпляр оси axes, используя метод add_axes в экземпляре fig класса Figure.

Слишком много теории? Попробуйте сами ниже.

fig = plt.figure()

x = np.arange(0,5,0.1)
y = np.sin(x)

# main axes
axes1 = fig.add_axes([0.1, 0.1, 0.9, 0.9]) # left, bottom, width, height (range 0 to 1)

# inner axes
axes2 = fig.add_axes([0.2, 0.2, 0.4, 0.4])

# main figure
axes1.plot(x, y, 'r') # 'r' = red line
axes1.set_xlabel('x')
axes1.set_ylabel('y')
axes1.set_title('Sine Wave')

# inner figure
x2 = np.arange(-5,5,0.1)
y2 = x2 ** 2
axes2.plot(x2,y2, 'g') # 'g' = green line
axes2.set_xlabel('x2')
axes2.set_ylabel('y2')
axes2.set_title('Square Wave')

plt.show()


Если вас не волнует конкретное расположение второго графика, попробуйте:

fig, axes = plt.subplots(nrows=1, ncols=3)

x = np.arange(-5,5,0.1)
y = x**2
i=1
for ax in axes:
    ax.plot(x, y, 'r')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('Square Wave '+str(i))
    i+=1


Это было легко, но не так уж и красиво с перекрывающимися осями графиков и метками, правда?

Мы можем справиться с этим с помощью метода fig.tight_layout, который автоматически регулирует положение осей, чтобы не было перекрывающегося содержимого. Причем размер рисунка по умолчанию фиксирован, т.е. не меняется в зависимости от количества графиков на рисунке.

fig, axes = plt.subplots(nrows=1, ncols=3)

x = np.arange(0,5,0.1)
y = x**2
i=1
for ax in axes:
    ax.plot(x, y**(i+1), 'r')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('Wave '+str(i))
    i+=1
fig.tight_layout()


Вышеуказанный набор графиков можно получить также с помощью метода add_subplot объекта figure.

fig = plt.figure()

for i in range(1,4):
    ax = fig.add_subplot(1, 3, i) # (rows amount, columns amount, subplot number)
    ax.plot(x, y**(i+1), 'r')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('Wave '+str(i))
    # clear x and y ticks
    # ax.set_xticks([])
    # ax.set_yticks([])
fig.tight_layout()
plt.show()


ncols, nrows = 3, 3

fig, axes = plt.subplots(nrows, ncols)

for m in range(nrows):
    for n in range(ncols):
        axes[m, n].set_xticks([])
        axes[m, n].set_yticks([])
        axes[m, n].text(0.5, 0.5, "axes[{}, {}]".format(m, n),
            horizontalalignment='center')


subplot2grid - это вспомогательная функция, которая похожа на plt.subplot, но использует индексирование на основе 0 и позволяет вложенному графику занимать несколько ячеек. Посмотрим, как это работает.

fig = plt.figure()

# Let's remove all labels on the axes
def clear_ticklabels(ax):
    ax.set_yticklabels([])
    ax.set_xticklabels([])

ax0 = plt.subplot2grid((3, 3), (0, 0))
ax1 = plt.subplot2grid((3, 3), (0, 1))
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (2, 0), colspan=3)
ax4 = plt.subplot2grid((3, 3), (0, 2), rowspan=2)

axes = (ax0, ax1, ax2, ax3, ax4)
# Add all sublots
[ax.text(0.5, 0.5, "ax{}".format(n), horizontalalignment='center') for n, ax in enumerate(axes)]
# Cleare labels on axes
[clear_ticklabels(ax) for ax in axes]
plt.show()



Размер рисунка, соотношение сторон и DPI

Matplotlib позволяет указывать соотношение сторон, DPI и размер рисунка при создании объекта Figure, используя аргументы figsize и dpi. figsize - это tuple из ширины и высоты рисунка в дюймах, а dpi - это количество точек на дюйм (пикселей на дюйм). Чтобы создать фигуру размером 800x400 пикселей, 100 точек на дюйм, необходимо:

fig = plt.figure(figsize=(8,4), dpi=100)

<Figure size 800x400 with 0 Axes>
fig, axes = plt.subplots(figsize=(12,3))

axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')


Комментариев нет:

Отправить комментарий