#!/usr/bin/env python # coding: utf-8 # # Основы программирования в Python # # *Алла Тамбовцева* # ### Основы работы с библиотекой `matplotlib` # С библиотекой `matplotlib` мы уже сталкивались, когда строили статистические графики на основе данных из датафреймов `pandas`. Но с помощью `matplotlib` можно строить не только гистограммы, графики плотности и диаграммы рассеяния, но и вообще любые графики. # # Для начала построим простенький график для визуализации данных в двух списках. Импортируем модуль pyplot из библиотеки и добавим питоновскую "магическую" строчку для того, чтобы графики отображались прямо в ipynb-файле. # In[5]: import matplotlib.pyplot as plt get_ipython().run_line_magic('', 'matplotlib inline') # Создадим два небольших списка. # In[6]: X = [-2, -0.5, 0, 2, 5, 8, 9, 10] Y = [4, 0.25, 0, 4, 25, 64, 81, 100] # Построим график. # In[7]: plt.plot(X,Y) # Как можно заметить, в списке `Y` сохранены элементы списка `X`, возведенные в квадрат. Однако наш график не похож на ветвь параболы, он какой-то угловатый. Это нормально, потому что в списках у нас всего по 8 элементов, то есть, всего 8 точек на графике соединяются линиями. Если бы точек было больше, график был бы более гладким. Воспользуемся функцией `linspace` из библиотеки `numpy` (вот она нам и пригодилась!). # In[8]: import numpy as np # In[9]: x = np.linspace(-2, 10, 100) # 100 точек x # In[10]: plt.plot(x, x**2) # Так график больше похож на параболу. Могли бы изобразить ее полностью, определенную на участке от -10 до 10. # In[11]: x = np.linspace(-10, 10, 200) plt.plot(x, x**2) # Поменяем цвет линии по умолчанию на какой-нибудь другой. # In[12]: plt.plot(x, x**2, 'lightblue') # Или так: # In[14]: plt.plot(x, x**2, 'red') # Список цветов в Python см. [здесь](https://matplotlib.org/users/colors.html). # # Теперь изменим тип линии. По умолчанию используется сплошная линия, но ее можно заменить на пунктирную или что-то подобное: # In[17]: plt.plot(x, x**2, 'red', linestyle = '--') # In[18]: plt.plot(x, x**2, 'red', linestyle = '-.') # Список всех типов линий см. [здесь](https://matplotlib.org/gallery/lines_bars_and_markers/line_styles_reference.html). # Кроме того, можно изменить толщину линии, добавив аргумент `linewidth`. # In[24]: plt.plot(x, x**2, 'red', linewidth = 3) # Теперь построим график, состоящий только из точек (можно считать диаграммой рассеяния). # In[25]: plt.scatter(X, Y) # Теперь будем менять цвет точек и тип точек (тип маркера) одновременно. # In[26]: plt.scatter(X, Y, color ='red', marker = 'o') # In[27]: plt.scatter(X, Y, color ='red', marker = '*') # In[28]: plt.scatter(X, Y, color ='green', marker = '2') # Список маркеров смотри [здесь](https://matplotlib.org/api/markers_api.html). # Если бы все строки кода со `scatter()` были в одной ячейке, то графики бы просто накладывались друг на друга. # In[30]: plt.scatter(X, Y, color ='red', marker = 'o') plt.scatter(X, Y, color ='blue', marker = '*') plt.scatter(X, Y, color ='green', marker = '2') # Если присмотреться, то на красных точках можно увидеть синие звездочки и зеленые треугольники. Чтобы такого не происходило (например, если вы создаете и сохраняете графики в цикле в пределах одной ячейки), нужно добавить строку с функцией `clf()`, которая очищает координатную плоскость для следующего графика (*clf* ‒ от *clear figure*). # In[31]: plt.scatter(X, Y, color ='red', marker = 'o') plt.clf() plt.scatter(X, Y, color ='blue', marker = '*') # На плоскости представлен только последний график с синими звездочками, красные точки от первого графика был стерты с помощью `clf()`. # При построении графиков стоит иметь в виду, что функция `plot()` всегда соединяет точки, причем последовательно, в том порядке, в котором они следуют в списках или массивах. Из-за этой особенности, допустив ошибку, связанную с заданием неверной области определения функции, можно получить некорректные графики. Построим для примера гиперболу. # In[32]: x = np.linspace(-100, 100, 100) y = 1/x plt.plot(x, y) # Полученный график не совсем похож на гиперболу! Как известно, в точке $x=0$ график уходит на бесконечность, линия при $x=0$ отсутствует. А здесь она есть! Избавимся от нее, построив график "по кусочкам". # In[35]: x1 = np.linspace(-100, 0, 100) # x < 0 y1 = 1/x1 x2 = np.linspace(0, 100, 100) # x > 0 y2 = 1/x2 plt.plot(x1, y1, 'blue') plt.plot(x2, y2, 'blue') # В завершение попробуем построить целый рисунок (*figure*), состоящий сразу из нескольких графиков (подграфиков). Построим разные типы функций: $y=x^2$, $y=x^3$, $y=e^x$ и $y=|x|$. Сначала создадим соответствующие массивы значений: # In[36]: x = np.linspace(-100, 100, 100) y = x ** 2 z = x ** 3 r = np.exp(x) m = abs(x) # Создадим рисунок (*figure*): # In[37]: plt.figure(1) # А теперь будем добавлять в него графики, указывая их расположение. В функции `subplot()` указывается число. Первые две цифры ‒ это число графиков в строке и столбце (здесь 2 на 2, поэтому `22`). Последняя цифра ‒ это положение графика: левый верхний угол (`1`), правый верхний угол (`2`), левый нижний угол (`3`), правый нижний угол (`4`). # In[39]: plt.subplot(221) plt.plot(x, y) # x^2 plt.title('parabola') plt.grid(True) plt.subplot(222) plt.plot(x, z) # x^3 plt.title('hyperbola') plt.grid(True) plt.subplot(223) plt.plot(x, r) # e^x plt.title('exponent') plt.grid(True) plt.subplot(224) plt.plot(x, m) # |x| plt.title('abs') plt.grid(True) # Строка `plt.grid(True)` нужна для того, чтобы на графиках были добавлены линии разметки, привычные нам "клеточки", которые позволяют удобным образом определять координаты точек на графике. # И напоследок: как сохранить график в файл. Очень просто. Например, так. # In[40]: plt.figure(1) plt.scatter(X, Y, color ='red', marker = '*') plt.savefig('MyScatter.png') # ищем файл в рабочей папке (рядом с текущим ipynb-файлом) # Мы достаточно кратко обсудили возможности библиотеки `matplotlib`, но на этом ее возможности не заканчиваются. Кому интересно, стоит посмотреть документацию по `matplotlib`, а также заглянуть в галерею с примерами графиков, которые можно адаптировать под свои задачи и данные. # # Если кто-то привык работать в R и полюбил вид графиков `ggplot2`, можно установить [библиотеку](http://ggplot.yhathq.com/install.html) `ggplot` для Python. Кроме того, можно поработать с библиотекой [seaborn](https://seaborn.pydata.org/), она предоставляет много возможностей для построения статистических графиков, и выглядят ти графики тоже очень симпатично. # # Если хочется более продвинутой интерактивной графики, связанной со статистическими моделями, стоит обратить внимание на библиотеку GraphLab. Она интересна не только графикой, но и другими вещами, но есть один минус: библиотека платная. Однако есть возможность получить доступ по учебной лицензии и даже продлевать ее, особенно, если учесть, что GraphLab используется в некоторых курсах на Coursera, что тоже облегачает получение доступа ([пример](https://www.coursera.org/learn/ml-foundations/home/welcome) такого курса).