ФИВТ МФТИ

Курс математической статистики

Никита Волков (email, VK)

Справочник по Python

Очень коротко базовые понятия Python

Подробно можно прочитать в статьях:

Python 2: https://habrahabr.ru/post/61905/

Python 3: https://ru.wikibooks.org/wiki/Python/%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA_Python_3.1

Арифметические операции и печать

In [1]:
print(1 + 2, 5 * 6, 54 / 5, 54 // 5, 2 ** 3)
3 30 10.8 10 8
In [2]:
x = 1
x += 2
y = x / 2
print('x = {}, y = {}'.format(x, y))
x = 3, y = 1.5

Условные операторы

In [3]:
if x > 2 and not 2 <= y < 3:
    print(True)
else:
    print(False)
True

Циклы

In [4]:
x = 0
for i in range(5):
    x += i
    
print('x = {}, range(5) = {}'.format(x, list(range(5))))
x = 10, range(5) = [0, 1, 2, 3, 4]

Но тут можно и проще

In [5]:
print(sum([i for i in range(5)]))
print(sum(range(5)))
10
10
In [6]:
order = ['Сначала', 'Потом', 'Затем']
courses = ['Теория вероятностей', 'Математическая статистика', 'Случайные процессы']
for preposition, course in zip(order, courses):
    print(preposition, course.lower())
Сначала теория вероятностей
Потом математическая статистика
Затем случайные процессы

Если у вас русский язык не работает, поставьте u перед строками. Например, u'текст'.

In [7]:
x = 1
while x < 12:
    x += x
print(x)
16

Листы и туплы

In [8]:
x = [1, 2, 3]  # лист
y = (1, 2, 3)  # тупл
print(type(x), type(y))
<class 'list'> <class 'tuple'>

Листы изменяемые

In [9]:
x.append(4)
print(x)
x += [5]
print(x)
x = x * 2
print(x)
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
In [10]:
y.append(4)  # туплы не изменяемые
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-89acde7fc93a> in <module>()
----> 1 y.append(4)  # туплы не изменяемые

AttributeError: 'tuple' object has no attribute 'append'

Срезы

In [11]:
x = list(range(10))
print(x[3:6])
print(x[:5])
print(x[5:])
print(x[1:9:2])  # Через один
print(x[::2])
print(x[:-1])  # Все, кроме последнего
print(x[-1])  # Последний
[3, 4, 5]
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[1, 3, 5, 7]
[0, 2, 4, 6, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
9

Функции

In [12]:
from math import sqrt, e, pi

def normal_density(x, a, sigma):
    return (1 / sqrt(2 * pi * sigma ** 2)) * e ** (-(x - a) ** 2 / (2 * sigma ** 2))

standart_normal_density = lambda x: normal_density(x, 0, 1)

print('{:.4f}'.format(normal_density(0, 1, 5)))
print('{:.4f}'.format(standart_normal_density(0)))
0.0782
0.3989

Некоторые полезные функции

In [13]:
# zip --- скрещивает два массива одной длины
x = zip(range(5), range(0, 10, 2))
print(list(x))

# map --- применяет функию к каждому элементу массива
x = map(lambda tmp: tmp ** 2, range(5))
print(list(x))

# sorted --- сортировка
x = list(zip([7, 3, 4, 4, 5, 3, 9], ['a', 'n', 'n', 'a', 'k', 'n', 'a']))
# сначала сортировка по букве по алфавиту, потом сортировка по убыванию по числу 
x = sorted(x, key=lambda element: (element[1], -element[0]))
print(list(x))
[(0, 0), (1, 2), (2, 4), (3, 6), (4, 8)]
[0, 1, 4, 9, 16]
[(9, 'a'), (7, 'a'), (4, 'a'), (5, 'k'), (4, 'n'), (3, 'n'), (3, 'n')]
In [14]:
x
Out[14]:
[(9, 'a'), (7, 'a'), (4, 'a'), (5, 'k'), (4, 'n'), (3, 'n'), (3, 'n')]

Сохрание в файл и чтение

In [15]:
# Сохранение
with open('example.txt', 'w') as f:
    for element in x:
        f.write(' '.join([str(element[0]), element[1]]))
        f.write('\n')
        
# Чтение
with open('example.txt') as f:
    for line in f:
        print(line[:-1])  # лишний перевод строки убираем
        print(line[:-1].split(' '))
9 a
['9', 'a']
7 a
['7', 'a']
4 a
['4', 'a']
5 k
['5', 'k']
4 n
['4', 'n']
3 n
['3', 'n']
3 n
['3', 'n']

Некоторые полезные типы данных

Множество (в нем элементы не упорядочены и не повторяются)

In [16]:
x = set([1, 4, 2, 4, 2, 1, 3, 4])
print(x)

x.add(5)  # добавление элемента
print(x)

x.pop()  # удаление элемента
print(x)

print(x.intersection(set([2, 4, 6, 8])))  # Пересечение
print(x.difference(set([2, 4, 6, 8])))  # Разность
print(x.union(set([2, 4, 6, 8])))  # Объединение
print(x.symmetric_difference(set([2, 4, 6, 8])))  # Симметрическая разность

print(x.issubset(set([2, 4, 6, 8])))  # Является ли подмножеством
print(x.issubset(set(list(range(10)))))

print(x.issuperset(set([2, 4, 6, 8])))  # Является ли надмножеством
print(x.issuperset(set([2, 4])))
{1, 2, 3, 4}
{1, 2, 3, 4, 5}
{2, 3, 4, 5}
{2, 4}
{3, 5}
{2, 3, 4, 5, 6, 8}
{3, 5, 6, 8}
False
True
False
True

Словари

Пример: словарь "распределение - количество параметров"

In [17]:
x = dict()
x['Normal'] = 2
x['Bernoulli'] = 1
x['Poisson'] = 1

x['Gamma'] = 1  # если ошиблись,
x['Gamma'] = 2  # то можно исправить

print('Normal' in x, 'Cauchy' in x)
print('keys:', x.keys())
print('values:', x.values())

for key in x:
    print('{} имеет {} параметр{}'.format(key, x[key], 'а' if x[key] == 2 else ''))
True False
keys: dict_keys(['Normal', 'Bernoulli', 'Gamma', 'Poisson'])
values: dict_values([2, 1, 2, 1])
Normal имеет 2 параметра
Bernoulli имеет 1 параметр
Gamma имеет 2 параметра
Poisson имеет 1 параметр

Библиотека numpy

In [18]:
import numpy as np

Самое основное — класс `numpy.array`

In [19]:
x = [1, 2, 3, 4]
x = np.array(x)
print(x)
x
[1 2 3 4]
Out[19]:
array([1, 2, 3, 4])

С ним удобно производить арифметические операции

In [20]:
print(x + 1)
print(x * 2)
print(x / 2)
print(x + [0, 3, 5, 1])
print(x * [0, 3, 5, 1])
print(x ** 2)
[2 3 4 5]
[2 4 6 8]
[ 0.5  1.   1.5  2. ]
[1 5 8 5]
[ 0  6 15  4]
[ 1  4  9 16]

Есть встроенные функции

In [21]:
print(x.sum())  # или np.sum(x) --- сумма всех элементов
print(x.prod())  # или np.prod(x) --- произведение всех элементов
print(np.sqrt(x))
print(np.exp(x))
print(np.log(x))
print(np.sin(x))
print(np.e, np.pi)
10
24
[ 1.          1.41421356  1.73205081  2.        ]
[  2.71828183   7.3890561   20.08553692  54.59815003]
[ 0.          0.69314718  1.09861229  1.38629436]
[ 0.84147098  0.90929743  0.14112001 -0.7568025 ]
2.718281828459045 3.141592653589793

Такие же срезы

In [22]:
x = np.array(range(10))
print(x[3:6])
print(x[:5])
print(x[5:])
print(x[1:9:2])  # Через один
print(x[::2])
print(x[:-1])  # Все, кроме последнего
print(x[-1])  # Последний
[3 4 5]
[0 1 2 3 4]
[5 6 7 8 9]
[1 3 5 7]
[0 2 4 6 8]
[0 1 2 3 4 5 6 7 8]
9

Последовательности

In [23]:
# стандартные range(stop) или range(start, stop[, step]), причем все параметры целочисленные
print(list(range(7)), list(range(1, 7)), list(range(1, 7, 2)))

# аналог из numpy, причем допускаются нецелые параметры
print(np.arange(7), np.arange(1, 7), np.arange(1, 7, 2))
print(np.arange(7.5), np.arange(1.5, 7.1), np.arange(1.5, 7.1, 1.3))

# а если надо указывать не шаг, а количество, то
print(np.linspace(0, 1, 11))  # (begin, end, count)

# или можно использовать логарифмическую шкалу
print(np.logspace(0, 1, 11, base=2))  # np.logspace(a, b, c, base) = base ** np.linspace(a, b, c)
[0, 1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6] [1, 3, 5]
[0 1 2 3 4 5 6] [1 2 3 4 5 6] [1 3 5]
[ 0.  1.  2.  3.  4.  5.  6.  7.] [ 1.5  2.5  3.5  4.5  5.5  6.5] [ 1.5  2.8  4.1  5.4  6.7]
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]
[ 1.          1.07177346  1.14869835  1.23114441  1.31950791  1.41421356
  1.51571657  1.62450479  1.74110113  1.86606598  2.        ]

Массив из нулей или из единиц

In [24]:
print(np.zeros(5))
print(np.ones(5))
[ 0.  0.  0.  0.  0.]
[ 1.  1.  1.  1.  1.]

Типы

In [25]:
x = np.linspace(0, 5, 11)
print(x)
print(x.dtype)

print(x.astype(int))
print(x.astype(str))
[ 0.   0.5  1.   1.5  2.   2.5  3.   3.5  4.   4.5  5. ]
float64
[0 0 1 1 2 2 3 3 4 4 5]
['0.0' '0.5' '1.0' '1.5' '2.0' '2.5' '3.0' '3.5' '4.0' '4.5' '5.0']

Двумерные массивы

Создание

In [26]:
X = np.arange(12).reshape(3, 4)  # Создаем массив размера 12 и меняем размерность
print(X)
print(X.shape)

print(X.reshape(4, 3))  # Можно снова изменить размер
print(X.shape)
print(X.ravel())  # Или растянуть его в одномерный массив
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
(3, 4)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
(3, 4)
[ 0  1  2  3  4  5  6  7  8  9 10 11]

Суммы, максимум, минимум

In [27]:
print(X.sum(), X.prod(), X.max(), X.min())  # По всему массиву
print(X.sum(axis=0), X.prod(axis=0), X.max(axis=0), X.min(axis=0))  # По столбцам
print(X.sum(axis=1), X.prod(axis=1), X.max(axis=1), X.min(axis=1))  # По строкам
66 0 11 0
[12 15 18 21] [  0  45 120 231] [ 8  9 10 11] [0 1 2 3]
[ 6 22 38] [   0  840 7920] [ 3  7 11] [0 4 8]

Арифметические операции (все операции поэлементные)

In [28]:
print(X)
print(X + 1)
print(X * 2)
print(X + [0, 0, 1, 1])  # второе слагаемое дополняется до матрицы копированием строк
print(X + np.array([[0, 0, 2]]).T)  # .T - транспонирование
print(X + X)
print(X * X)  # только одного размера
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
[[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]]
[[ 0  1  3  4]
 [ 4  5  7  8]
 [ 8  9 11 12]]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [10 11 12 13]]
[[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]]
[[  0   1   4   9]
 [ 16  25  36  49]
 [ 64  81 100 121]]

А вот так уже не получится

In [29]:
print(X.T * X)  # размеры не совпадают
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-29-c24ebaa1cfa3> in <module>()
----> 1 print(X.T * X)  # размеры не совпадают

ValueError: operands could not be broadcast together with shapes (4,3) (3,4) 

Для этого есть класс `numpy.matrix`, в котором операция умножения определена как матричное умножение

In [30]:
X = np.matrix(X)  # Преобразование типов
print(X.T * X)
[[ 80  92 104 116]
 [ 92 107 122 137]
 [104 122 140 158]
 [116 137 158 179]]

Зато тут уже поэлементно не получится

In [31]:
print(X * X)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-31-eaca4c4d9d7d> in <module>()
----> 1 print(X * X)

/usr/local/lib/python3.4/dist-packages/numpy/matrixlib/defmatrix.py in __mul__(self, other)
    341         if isinstance(other, (N.ndarray, list, tuple)) :
    342             # This promotes 1-D vectors to row vectors
--> 343             return N.dot(self, asmatrix(other))
    344         if isscalar(other) or not hasattr(other, '__rmul__') :
    345             return N.dot(self, other)

ValueError: shapes (3,4) and (3,4) not aligned: 4 (dim 1) != 3 (dim 0)

Многомерные массивы

In [32]:
X = np.arange(24).reshape(2, 3, 4)
print(X)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]

Суммирование (аналогично остальные)

In [33]:
# суммируем только по нулевой оси, то есть для фиксированных j и k суммируем только элементы с индексами (*, j, k)
print(X.sum(axis=0))
# суммируем сразу по двум осям, то есть для фиксированной i суммируем только элементы с индексами (i, *, *)
print(X.sum(axis=(1, 2)))
[[12 14 16 18]
 [20 22 24 26]
 [28 30 32 34]]
[ 66 210]

Сортировка

In [34]:
X = np.array([2, 6, 3, 7, 1, 4, 3, 8, 10, 5, 6, 3])
print(np.sort(X, kind='mergesort'))

X = X.reshape(3, 4)
print(X)
X = np.sort(X, axis=1, kind='quicksort')  # сортировка тут только по одной координате. По нескольким нельзя
print(X)
[ 1  2  3  3  3  4  5  6  6  7  8 10]
[[ 2  6  3  7]
 [ 1  4  3  8]
 [10  5  6  3]]
[[ 2  3  6  7]
 [ 1  3  4  8]
 [ 3  5  6 10]]

Сохранение в файл и чтение из файла

In [35]:
x = np.arange(0, 25, 0.5).reshape((5, 10))

# Сохраняем в файл example.txt данные x в формате с двумя точками после запятой и разделителем ';'
np.savetxt('example.txt', x, fmt='%.2f', delimiter=';')

Получится такой файл

In [36]:
with open('example.txt') as f:
    print(''.join(f.readlines())[:-1])
0.00;0.50;1.00;1.50;2.00;2.50;3.00;3.50;4.00;4.50
5.00;5.50;6.00;6.50;7.00;7.50;8.00;8.50;9.00;9.50
10.00;10.50;11.00;11.50;12.00;12.50;13.00;13.50;14.00;14.50
15.00;15.50;16.00;16.50;17.00;17.50;18.00;18.50;19.00;19.50
20.00;20.50;21.00;21.50;22.00;22.50;23.00;23.50;24.00;24.50

Теперь его можно прочитать

In [37]:
x = np.loadtxt('example.txt', delimiter=';')
print(x)
[[  0.    0.5   1.    1.5   2.    2.5   3.    3.5   4.    4.5]
 [  5.    5.5   6.    6.5   7.    7.5   8.    8.5   9.    9.5]
 [ 10.   10.5  11.   11.5  12.   12.5  13.   13.5  14.   14.5]
 [ 15.   15.5  16.   16.5  17.   17.5  18.   18.5  19.   19.5]
 [ 20.   20.5  21.   21.5  22.   22.5  23.   23.5  24.   24.5]]

Библиотека scipy (модуль scipy.stats)

Нам пригодится только модуль scipy.stats. Полное описание http://docs.scipy.org/doc/scipy/reference/stats.html

In [38]:
import scipy.stats as sps

Общий принцип:

$X$ — некоторое распределение с параметрами params

  • $X$.`rvs(size=`$N$, `params)` — генерация выборки размера $N$ (Random VariateS). Возвращает `numpy.array`
  • $X$.`cdf(`$x$, `params)` — значение функции распределения в точке $x$ (Cumulative Distribution Function)
  • $X$.`logcdf(`$x$, `params)` — значение логарифма функции распределения в точке $x$
  • $X$.`ppf(`$q$, `params)` — $q$-квантиль (Percent Point Function)
  • $X$.`mean(params)` — математическое ожидание
  • $X$.`median(params)` — медиана
  • $X$.`var(params)` — дисперсия (Variance)
  • $X$.`std(params)` — стандартное отклонение = корень из дисперсии (Standard Deviation)

Кроме того для непрерывных распределений определены функции

  • $X$.`pdf(`$x$, `params)` — значение плотности в точке $x$ (Probability Density Function)
  • $X$.`logpdf(`$x$, `params)` — значение логарифма плотности в точке $x$

А для дискретных

  • $X$.`pmf(`$k$, `params)` — значение дискретной плотности в точке $k$ (Probability Mass Function)
  • $X$.`logpdf(`$k$, `params)` — значение логарифма дискретной плотности в точке $k$

Параметры могут быть следующими:

  • `loc` — параметр сдвига
  • `scale` — параметр масштаба
  • и другие параметры (например, $n$ и $p$ для биномиального)

Для примера сгенерируем выборку размера $N = 200$ из распределения $\mathscr{N}(1, 9)$ и посчитаем некоторые статистики. В терминах выше описанных функций у нас $X$ = sps.norm, а params = (loc=1, scale=3).

In [39]:
sample = sps.norm.rvs(size=200, loc=1, scale=3)
print('Первые 10 значений выборки:\n', sample[:10])
print('Выборочное среденее:', sample.mean())
print('Выборочная дисперсия:', sample.var())
Первые 10 значений выборки:
 [-2.06235463  1.59369232 -0.68126487  2.98438357 -1.24908635  2.03774639
  0.27700922 -0.89751906  3.70360346  3.74723375]
Выборочное среденее: 0.777590388762
Выборочная дисперсия: 8.90997270912
In [40]:
print('Плотность:\t\t', sps.norm.pdf([-1, 0, 1, 2, 3], loc=1, scale=3))
print('Функция распределения:\t', sps.norm.cdf([-1, 0, 1, 2, 3], loc=1, scale=3))
Плотность:		 [ 0.10648267  0.12579441  0.13298076  0.12579441  0.10648267]
Функция распределения:	 [ 0.25249254  0.36944134  0.5         0.63055866  0.74750746]
In [41]:
print('Квантили:', sps.norm.ppf([0.05, 0.1, 0.5, 0.9, 0.95], loc=1, scale=3))
Квантили: [-3.93456088 -2.8446547   1.          4.8446547   5.93456088]

Cгенерируем выборку размера $N = 200$ из распределения $Bin(10, 0.6)$ и посчитаем некоторые статистики. В терминах выше описанных функций у нас $X$ = sps.binom, а params = (n=10, p=0.6).

In [42]:
sample = sps.binom.rvs(size=200, n=10, p=0.6)
print('Первые 10 значений выборки:\n', sample[:10])
print('Выборочное среденее:', sample.mean())
print('Выборочная дисперсия:', sample.var())
Первые 10 значений выборки:
 [6 8 7 7 6 7 8 7 5 7]
Выборочное среденее: 6.135
Выборочная дисперсия: 2.466775
In [43]:
print('Дискретная плотность:\t', sps.binom.pmf([-1, 0, 5, 5.5, 10], n=10, p=0.6))
print('Функция распределения:\t', sps.binom.cdf([-1, 0, 5, 5.5, 10], n=10, p=0.6))
Дискретная плотность:	 [  0.00000000e+00   1.04857600e-04   2.00658125e-01   0.00000000e+00
   6.04661760e-03]
Функция распределения:	 [  0.00000000e+00   1.04857600e-04   3.66896742e-01   3.66896742e-01
   1.00000000e+00]
In [44]:
print('Квантили:', sps.binom.ppf([0.05, 0.1, 0.5, 0.9, 0.95], n=10, p=0.6))
Квантили: [ 3.  4.  6.  8.  8.]

Отдельно есть класс для многомерного нормального распределения. Для примера сгенерируем выборку размера $N=200$ из распределения $\mathscr{N} \left( \begin{pmatrix} 1 \\ 1 \end{pmatrix}, \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} \right)$.

In [45]:
sample = sps.multivariate_normal.rvs(mean=[1, 1], cov=[[2, 1], [1, 2]], size=200)
print('Первые 10 значений выборки:\n', sample[:10])
print('Выборочное среденее:', sample.mean(axis=0))
print('Выборочная матрица ковариаций:\n', np.cov(sample.T))
Первые 10 значений выборки:
 [[-0.27215325 -1.38637727]
 [-0.31050738  1.19181083]
 [ 1.89454062  1.05519067]
 [ 0.7639327   2.23128074]
 [-1.31920707 -0.31138659]
 [-0.13399183 -0.80243711]
 [-0.23527991  2.35924247]
 [ 0.58234234  0.95402281]
 [ 3.24374171  3.34295157]
 [ 0.67813213  2.21140736]]
Выборочное среденее: [ 0.87504233  1.05920753]
Выборочная матрица ковариаций:
 [[ 1.71268537  0.85696209]
 [ 0.85696209  1.89059004]]

Некоторая хитрость :)

In [46]:
sample = sps.norm.rvs(size=10, loc=np.arange(10), scale=0.1)
print(sample)
[ 0.05653714  0.98363644  2.11329714  2.95404412  4.21877038  5.03033628
  6.12153382  7.02678976  8.06310136  9.10200457]

Бывает так, что надо сгенерировать выборку из распределения, которого нет в `scipy.stats`. Для этого надо создать класс, который будет наследоваться от класса rv_continuous для непрерывных случайных величин и от класса rv_discrete для дискретных случайных величин. Пример есть на странице http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.rv_continuous.html#scipy.stats.rv_continuous

Для примера сгенерируем выборку из распределения с плотностью $f(x) = \frac{4}{15} x^3 I\{x \in [1, 2] = [a, b]\}$.

In [47]:
class cubic_gen(sps.rv_continuous):
    def _pdf(self, x):
        return 4 * x ** 3 / 15
cubic = cubic_gen(a=1, b=2, name='cubic')

sample = cubic.rvs(size=200)
print('Первые 10 значений выборки:\n', sample[:10])
print('Выборочное среденее:', sample.mean())
print('Выборочная дисперсия:', sample.var())
Первые 10 значений выборки:
 [ 1.7614412   1.77230539  1.98901154  1.84270094  1.29474504  1.77433049
  1.6724117   1.86960696  1.50343537  1.26115348]
Выборочное среденее: 1.658129845
Выборочная дисперсия: 0.0640721845104

Если дискретная случайная величина может принимать небольшое число значений, то можно не создавать новый класс, как показано выше, а явно указать эти значения и из вероятности.

In [48]:
some_distribution = sps.rv_discrete(name='some_distribution', values=([1, 2, 3], [0.6, 0.1, 0.3]))

sample = some_distribution.rvs(size=200)
print('Первые 10 значений выборки:\n', sample[:10])
print('Выборочное среденее:', sample.mean())
print('Частота значений по выборке:', (sample == 1).mean(), (sample == 2).mean(), (sample == 3).mean())
Первые 10 значений выборки:
 [1 1 3 1 3 1 1 1 1 1]
Выборочное среденее: 1.865
Частота значений по выборке: 0.53 0.075 0.395

Библиотека matplotlib

http://matplotlib.org/gallery.html (англ.) — тысячи примеров

In [49]:
import matplotlib.pyplot as plt

Для того, чтобы графики рисовались прямо в ноутбуке, нужно выполнить команду

In [51]:
%pylab inline
Populating the interactive namespace from numpy and matplotlib

Сгенерируем выборку из стандартного нормального распределения. Нанесем на график точки выборки.

In [53]:
sample = sps.norm.rvs(size=200)

plt.figure(figsize=(10, 1))  # размер графика
plt.scatter(sample, np.zeros(200), alpha=0.2)  # alpha - прозрачность точки
plt.show()

Можно добавить график плотности

In [54]:
grid = np.linspace(-3, 3, 100)  # задаем сетку для построения графика плотности

plt.figure(figsize=(10, 4))
plt.scatter(sample, np.zeros(200) - 0.02, alpha=0.2, label='sample')  # label - описание в легенде
plt.plot(grid, sps.norm.pdf(grid), color='red', label='density')  # color - цвет графика
plt.legend()  # добавляет легенду
plt.show()

Предположим, что выборка приходит постепенно. Для каждого момента времени посчитаем выборочное среднее и доверительный интервал. Нанесем их на график.

In [55]:
time = np.arange(1, 201)
means = sample.cumsum() / np.arange(1, 201)

plt.figure(figsize=(15, 8))
plt.scatter(time, sample, alpha=0.2, s=40, label='sample')  # s - размер точек
plt.plot(time, means, color='red', linewidth=2.5, label='sample mean $\overline{X}$')  # linewidth - толщина линии
# заполняет пространство между двумя функциями
plt.fill_between(time, means + 2 / np.sqrt(time), means - 2 / np.sqrt(time), alpha=0.1)
plt.legend()
plt.xlim((1, 200))  # размеры графика по горизонтальной оси (ставим None, если по стороне ограничений нет)
plt.ylim((-3, 3))  # размеры графика по вертикальной оси 
plt.xlabel('Time')  # название горизонтальной оси (аналогично plt.ylabel)
plt.title('Sample by time')  # имя графика
plt.grid()  # добавляем сетку
plt.savefig('example.png')  # сохранение в файл
plt.show()

Посмотрим еще на то, как можно закрашивать график в соответствии с какой-то функцией. Для примера возьмем плотность распределения $\mathscr{N} \left( \begin{pmatrix} 0 \\ 0 \end{pmatrix}, \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} \right)$.

In [56]:
grid = np.mgrid[-3:3:0.05, -3:3:0.05]
density = np.array([[sps.multivariate_normal.pdf((grid[0, i, j], grid[1, i, j]), mean=[0, 0], cov=[[2, 1], [1, 2]])
                       for i in range(grid[0].shape[0])]
                      for j in range(grid[0].shape[1])])

plt.figure(figsize=(14, 6))

subplot(1, 2, 1)
plt.pcolormesh(grid[0], grid[1], density, cmap='Oranges')  # закрасить с интенсивностью density, cmap - цветовая схема
plt.xlim((np.min(grid[0]) + 0.2, np.max(grid[0]) - 0.2))
plt.ylim((np.min(grid[1]) + 0.2, np.max(grid[1]) - 0.2))
plt.title('Gaussian density')

subplot(1, 2, 2)
CS = plt.contour(grid[0], grid[1], density, [0.005, 0.02, 0.05, 0.085])  # нарисовать указанные линии уровня
plt.clabel(CS, fontsize=14, inline=1, fmt='%1.3f')
plt.xlim((np.min(grid[0]), np.max(grid[0])))
plt.ylim((np.min(grid[1]), np.max(grid[1])))
    
plt.show()
/usr/local/lib/python3.4/dist-packages/matplotlib/collections.py:650: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
  if self._edgecolors_original != str('face'):

Итак, функции отрисовки

  • `plt.scatter(x, y, params)` — нарисовать точки с координатами из $x$ по горизонтальной оси и из $y$ по вертикальной оси
  • `plt.plot(x, y, params)` — нарисовать график по точкам с координатами из $x$ по горизонтальной оси и из $y$ по вертикальной оси. Точки будут соединятся в том порядке, в котором они указаны в этих массивах.
  • `plt.fill_between(x, y1, y2, params)` — закрасить пространство между $y_1$ и $y_2$ по координатам из $x$.
  • `plt.pcolormesh(x1, x1, y, params)` — закрасить пространство в соответствии с интенсивностью $y$.
  • `plt.contour(x1, x1, y, lines)` — нарисовать линии уровня. Затем нужно применить `plt.clabel`

Вспомогательные функции

  • `plt.figure(figsize=(x, y))` — создать график размера $(x, y)$
  • `plt.show()` — показать график.
  • `plt.subplot(...)` — добавить подграфик
  • `plt.xlim(x_min, x_max)` — установить пределы графика по горизонтальной оси
  • `plt.ylim(y_min, y_max)` — установить пределы графика по вертикальной оси
  • `plt.title(name)` — установить имя графика
  • `plt.xlabel(name)` — установить название горизонтальной оси
  • `plt.ylabel(name)` — установить название вертикальной оси
  • `plt.legend(loc=...)` — сделать легенду в позиции loc
  • `plt.grid()` — добавить сетку на график
  • `plt.savefig(filename)` — сохранить график в файл

Посмотрим еще, как рисовать 3D-графики

In [57]:
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(16, 10))
ax = fig.gca(projection='3d')
surf = ax.plot_surface(grid[0], grid[1], density, rstride=1, cstride=1, cmap='Oranges_r',
                       linewidth=0, antialiased=False)
ax.set_zlim(0, 0.1)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Можно загрузить картинку из файла. Это будет обычный numpy.array. Размерность картинки $280 x 280$. По последней координате цвета RGB и прозрачность.

In [58]:
picture = plt.imread('python.png')
print(type(picture), picture.shape)

plt.imshow(picture)
plt.axis('off')
plt.show()
<class 'numpy.ndarray'> (280, 280, 4)

У функций в matplotlib много параметров. Для того, чтобы посмотреть все параметры, можно воспользоваться справкой.

In [59]:
# help(plt.plot)