Программирование и научные вычисления на языке Python/§10

Во всех предыдущих случаях мы строили обычные графики в виде кривых. Но довольно часто в исследованиях применяются и другие наглядные способы представления данных, такие как гистограммы, круговые, точечные, кольцевые, пузырьковые диаграммы, представление в полярной системе координат и так далее. Мы рассмотрим общие принципы построения других видов графиков и, таким образом, продолжим рассмотрение библиотек Matplotlib и NumPy.



## Гистограммы

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



```
import matplotlib.pyplot as plt
import numpy as np
y = np.random.randn(1000)
plt.hist(y, 25)
plt.show()
```


Не удивляйтесь, если картинка, которую вы получите, будете отличаться от приведенной. Дело в том, что в инструкции `np.random.randn(1000)` создается массив из случайных точек в соответствии с Гауссовым распределением. Эта рандомность и ограниченность числа точек вносит свой вклад.

Как мы видим, в отличие от ранее применяемой функции `plot()` для кривых, используется `hist()` ( histogram). Первым аргументом она принимает массив чисел, вторым необязательным аргументом является число полос, на которые будет разбит массив. По умолчанию это число равно десяти, мы присвоили ему значение 25.

## Учет ошибок

В практической науке, эксперимент даже при максимальной точности измерений всегда вносит свою погрешность. Для того, чтобы учесть это и указать возможный разброс вокруг значения, считаемого истинным, вводят error bars, которые на кривой для полученных точек показывают своеобразный доверительный интервал:



```
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 4, 0.2)
y = np.exp(-x)
e1 = 0.1 * np.abs(np.random.randn(len(y)))
plt.errorbar(x, y, yerr=e1, fmt='.-')
plt.show()
```


Итак, с помощью функции `arange()` мы создали массив точек *x* от 0 до 4 с шагом 0.2. Далее получили массив точек *y*, отвечающих за значения функции *exp(-x)*. Эти действия ничем не отличаются от тех, что мы делали раньше, когда строили графики кривых. В следующей мы вносим случайные ошибки: определяем размера массива *y*, составляем для него соответствующий массив гауссово распределенных вокруг нуля случайных чисел, функция `abs()` берет от них модуль, так чтобы все числа были неотрицательными и домножаем на 0.1, так чтобы эти ошибки не были слишком большими для нашего графика.

Далее мы видим, что полученная последовательность указывается в функции `errorbar()` в виде аргумента `yerr` и последовательно накладывается на полученный график *y(x)*, вид которого определяется параметром `fmt`. Если существуют ошибки не только по *y*-значенимя, но и по *x*, то имеется эквивалентный аргумент `xerr`. Соответствующие засечки будут иметь вид крестов.

Передаваемый аргумент `fmt` может иметь значение `None`, тогда на экран выводятся только error bars, без графика. Функция `errorbar()` также имеет другие keywords: `ecolor` и `elinewidth` определяют соответственно цвет и толщину линии, показывающей интервал, `capsize` задает ширину ограничивающих крышечек (в пикселях).

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



```
plt.errorbar(x, y, yerr=[e1,e2], fmt='.-')
```



## Диаграммы-столбцы

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

Для визуализации используется функция `bar()`, принимающая две последовательности координат: *x*, определяющих левый край столбца и *y*, определяющих высоту. Ширина прямоугольников по умолчанию равно 0.8. Но этот и другие параметры можно менять за счет keywords:

`width`задает ширину прямоугольника`color`задает цвет прямоугольника`xerr, yerr`позволяют устанавливать error bars

Соберем и проиллюстрируем наши знания в некотором комплексном примере:



```
import matplotlib.pyplot as plt
import numpy as np
data1=10*np.random.rand(5)
data2=10*np.random.rand(5)
data3=10*np.random.rand(5)
locs = np.arange(1, len(data1)+1)
width = 0.27
plt.bar(locs, data1, width=width)
plt.bar(locs+width, data2, width=width, color='red')
plt.bar(locs+2*width, data3, width=width, color='green')
plt.xticks(locs + width*1.5, locs)
plt.show()
```


Генерируем последовательности трех видов данных (data) для пяти точек. Задаем переменную, которая будет определять толщину столбцов. Первый аргумент bar() имеет такой вид для того, чтобы три столбца стояли вместе, впритык друг к другу. Также здесь применяется фокус с функцией, известной из предыдущего урока — `xticks`, которая позволяет изменять засечки на оси абсцисс, и здесь мы смещаемся так, чтобы аргумент, породивший три своих столбца стоял посередине.

Часто используют и горизонтальное расположение. Оно описывается практически также, но вместо функции `bar()` используется `barh()`. Более того, такого рода диаграмм и возможностей существует великое множество и вы сами можете ознакомиться с ними по документации Matplotlib.



## Круговые диаграммы

Такой вид диаграмм используется, когда для нас существенно сравнение вклада каждого участника в общее дело. Поскольку это дело похоже на разрезание пирога, то и диаграммы также называют pie charts, а функцию `pie()`. Первым аргументом она принимает *x*-последовательность из внесенных единиц. Далее может следовать множество keywords:

`explode`— если задается, то представляет собой последовательность того же размера, что*x*.`colors`задает используемые цвета, в которые раскрашиваются куски «пирога»`labels`задает имена, по одному на каждый элемент x,`labeldistance`определяет радиальное расстояние на котором эти имена выводятся`autopct`задает тип форматирования численных значений`pctdistance`определяет расстояние от центра, на котором размещается число`shadow`добавляет тень

Давайте соберем вместе хотя бы некоторые из них:



```
import matplotlib.pyplot as plt
plt.figure(figsize=(7,5))
x = [18, 15, 11, 9, 8, 6]
labels = ['Java', 'C', 'C++', 'PHP', '(Visual) Basic', 'Python']
explode = [0, 0, 0, 0, 0, 0.2]
plt.pie(x, labels = labels, explode = explode, autopct = '%1.1f%%', shadow=True);
plt.show()
```


Как обычно, цвет чередуется и сам собой, порядок по умолчанию для matplotlib это blue, green, red, cyan, magenta, yellow. Кроме описанного выше, здесь мы видим еще инструкцию `figure(figsize=(7,5))`, которая, как несложно понять, задает размеры нашего эллипса.



## График рассеяния

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

Как вы уже, наверное, догадались в модуле matplotlib.pyplot имеется своя функция, для графика рассеяния (scatter plot) это функция `scatter()`

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

`s`задает размер маркеров и может быть как одним числом для всех, так и представлять массив значений`c`задает цвет маркеров, также либо один для всех, либо множество`marker`определяет тип маркера, поддерживается большинство типов, рассмотренных на предыдущем уроке

А вот и пример, породивший рисунок справа:



```
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000)
size = 50*np.random.randn(1000)
colors = np.random.rand(1000)
plt.scatter(x, y, s=size, c=colors)
plt.show()
```



## Полярные координаты

Кроме наиболее часто используемой декартовой системы координат, довольно широко применяется и полярная система координат, удобная в различных радиальных задачах, координаты точек в ней задается с помощью радиус-вектора ρ, идущего из начала координат и угла θ. Угол может быть задан в радианах или градусах, matplotlib использует градусы.

Для построения в полярных координат используется функция `polar()`. В аргументах первыми идут углы, потом радиусы. В следующем примере мы используем один и тот же массив для углов и радиус-векторов и рисуем три разные кривые. Первая образует спираль, поскольку с каждым новым углом меняется и радиус, вторая рисует цветок в соответствии с уравнением розы (вы уже могли заметить, что в numpy, поскольку он является математическим модулем, имеются и математические функции, например, косинус), последняя представляет собой окружности ввиду неизменности радиуса для всех углов (в данном случае он равен 1.4).



```
import matplotlib.pyplot as plt
import numpy as np
theta = np.arange(0., 2., 1./180.)*np.pi # 360 точек
plt.polar(3*theta, theta/5) # спираль
plt.polar(theta, np.cos(4*theta)) # уравнение розы
plt.polar(theta, [1.4]*len(theta)) # окружность
plt.show()
```



## Текст, примечания

Кроме текста в названиях, подписях к осям, легенде, можно непосредственно вставлять его в график с помощью простой функции `text(x , y, text)`, где *x* и *y* координаты, а *text* строковая строка. Эта функция вставляет текст в соответствии с координатами данных. Возможна вставка и в координатах графика, в которых за (0, 0) принимается нижний левый угол, а за (1, 1) правый верхний. Это делается с помощью функции `figtext(x, y, text)`.

Текстовые функции, вставляют конечно текст в график, но часто бывает нужно именно указать, выделить какой-то экстремум, необычную точку. Это легко сделать с помощью примечаний — функции `annotate('annotation', xy=(x1, y1), xytext=(x2, y2))`. Здесь вместо `annotation` мы пишем текст примечания, вместо (x1, y1) координаты интересной точки, вместо (x2, y2) координаты, где мы хотим вставить текст.