Скачать ipynb
python_digest

В данном ноутбуке мы быстро повторим основы библиотек Python для анализа данных. Если вы захотите более подробно разобраться в каком-то их разделов, смотрите Питон-ноутбуки и видеолекции на нашем сайте в разделе Python для анализа данных.

1. Anaconda

Anaconda — это дистрибутив Python, в который встроен пакетный менеджер conda. Этот инструмент позволяет выделить отдельные окружения для ваших проектов, например, на Python или R. В каждом конкретном окружении будут свои версии языков программирования и библиотек. Это позволит не запутаться в том, какие версии библиотек у вас установлены, а таже даст вам возможность переносить окружения.

Установку можете произвести с официального сайта.

Пример создания окружения mipt-stats:

conda create -n mipt-stats python=3.7 r=3.6 --yes

Активация и деактивация:

conda activate mipt-stats
conda deactivate

Чтобы поставить пакеты, используйте команду conda install:

conda install numpy

Чтобы понять, как работать с Anaconda оптимальнее, смотрите полную версию материала.

1.1 Альтернативы

  • Если вы используете Linux-систему, то чаще проще обойтись без Anaconda, а использовать pip, например,

    pip install numpy
    

    В таком случае тоже можно настроить виртуальное окружение. Однако не стоит смешивать использование pip и conda!

  • Если вы не хотите ничего себе устанавливать, например, из-за малых мощностей, можно использовать Google Colab. Но в таком случае каждый раз придется заново настраивать окружение, кроме того, среда выполнения может отключаться при длительном простое.

2. Jupyter

Jupyter предоставляет веб-интерфейс для редактирования jupyter-ноутбуков. Это удобный инструмент для того, чтобы быстро писать код на Python (или других языках), проверять гипотезы, строить графики, делать интерактивные визуализации и делиться результатами с коллегами.

Чтобы запустить интерфейс, поставьте в conda пакет jupyter и выполните в консоли команду

jupyter notebook

Jupyter-ноутбук состоит из ячеек с кодом, с markdown, а также с сырым текстом. Работать с ячейкой можно в двух режимах: Command Mode и Edit Mode. Чтобы переходить между ними, используйте Esc и Enter.

В Edit Mode управление похоже на vim, справку по Command Mode можно посмотреть с помощью сочетания клавиш Esc + H.

При написании кода, кроме функций языка программирования, можно пользоваться магией Юпитера, или jupyter magics. Это отдельный метаязык внутри jupyter, команды которого начинаются на %. Можете открыть список всех доступных команд:

In [36]:
%lsmagic
Out[36]:
Available line magics:
%alias  %alias_magic  %autoawait  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %conda  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %pip  %popd  %pprint  %precision  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%markdown  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

Есть magics, которые применяются к строке или всей клетке в целом. Чтобы посмотреть помощь по интересующей команде, можно вызвать help:

In [37]:
?%lsmagic

Впоследствии увидим, как можно замерить производительность вашей программы при помощи %%time.

Если хотите посмотреть подробный обзор jupyter magic, узнать о преимуществах Jupyter, узнать полезные сочетания клавиш и установить удобные плагины, обращайтесь к полным материалам по Jupyter.

3. NumPy

В пакете NumPy представлены удобные функции для работы c $n$-мерными массивами. В нём имеются функции для поэлементных операций, а также для работы с массивами, как с математическими объектами, например, функции для линейной алгебры.

Они реализованы на C++, поэтому гораздо эффективнее аналогичных реализаций на Python.

In [38]:
import numpy as np

3.1 Основы

Создавать массивы можно различными способами.

In [39]:
# Из списка
a = np.array([0, 2, 1])

# Из равномерной сетки
grid = np.linspace(0, 1, 500)

# Перечисление 0, 1, 2, 3, 4
nat_grid = np.arange(5)

# Заполненный нулями
zeros = np.zeros((1, 2, 3))

У массивов можно узнать их размерность, форму и число элементов

In [40]:
print(zeros.ndim, zeros.shape, zeros.size)
3 (1, 2, 3) 6

Индексация похожа на индексацию списков

In [41]:
print(a[2:1:-1])
print(grid[::100])
print(zeros[:, :2, :2])
[1]
[0.         0.2004008  0.4008016  0.6012024  0.80160321]
[[[0. 0.]
  [0. 0.]]]

3.2 Соединение массивов и их форма

Из одномерного массива можно сделать двумерный, указав необходимую форму.

In [42]:
A = np.arange(6).reshape((2, 3))
A
Out[42]:
array([[0, 1, 2],
       [3, 4, 5]])

Два массива можно склеить горизонтально

In [43]:
B = np.zeros((2, 5))
np.hstack([A, B])
Out[43]:
array([[0., 1., 2., 0., 0., 0., 0., 0.],
       [3., 4., 5., 0., 0., 0., 0., 0.]])

и вертикально

In [44]:
B = np.zeros((1, 3))
np.vstack([A, B])
Out[44]:
array([[0., 1., 2.],
       [3., 4., 5.],
       [0., 0., 0.]])

3.3 Операции над массивами

Обычные арифметические операции работают поэлементно.

In [45]:
a = np.array([1, 2, 3])
b = np.array([3, 4, 5])
In [46]:
print(a * b)
[ 3  8 15]
In [47]:
print(np.sin(a))
[0.84147098 0.90929743 0.14112001]

Двумерный массив можно умножить на одномерный, как матрицу на вектор. Операция @ реализует матричное умножение

In [48]:
A = np.ones((2, 3))
b = np.ones(3)
A @ b
Out[48]:
array([3., 3.])

Транспонировать матрицу можно с помощью метода T

In [49]:
A.T.shape
Out[49]:
(3, 2)

3.4 Способы суммирования

Простое суммирование возвращает сумму всех элементов массива.

In [51]:
print(np.sum(a))
print(a.sum())
6
6

С многомерными массивами суммирование может работать сложнее. Например, можно суммировать вдоль определённой оси и получать не одно число, а массив.

In [52]:
a = np.ones((3, 4), dtype=int)
print(a.sum(axis=1))
print(a.sum(axis=0))
[4 4 4]
[3 3 3 3]

Для более продвинутых способов суммирования существуют, например, суммы Эйнштейна.

In [53]:
A = np.array([0, 1, 2])
B = np.array([[10, 15, 20], [100, 150, 200]])
print(A)
print(B)
[0 1 2]
[[ 10  15  20]
 [100 150 200]]
In [54]:
np.einsum('i,ji->j', A, B)
Out[54]:
array([ 55, 550])

В данном случае индексы суммирования приводят к такому вычислению:

  • $c_0 = a_0 \cdot b^0_0 + a_1 \cdot b^1_0 + a_2 \cdot b^2_0$. В нашем случае: $c_0 = 0 \cdot 1 + 1 \cdot 15 + 2 \cdot 20$.
  • $c_1 = a_0 \cdot b^0_1 + a_1 \cdot b^1_1 + a_2 \cdot b^2_1$. В нашем случае: $c_1 = 0 \cdot 1 + 1 \cdot 150 + 2 \cdot 200$.

Чтобы подробно разобраться в синтаксисе, посмотрите полный материал.

3.5 Бродкастинг

Broadcasting — процедура обработки массивов с различными формами во время арифметических операций. При соблюдении определенных ограничений меньший массив приводится к форме по большему массиву.

Рассмотрим поэлементное умножение двух массивов одинаковой формы

In [55]:
a = np.array([1.0, 2.0, 3.0])
b = np.array([2.0, 2.0, 2.0])
a * b
Out[55]:
array([2., 4., 6.])

А теперь массивы разной формы

In [56]:
a = np.array([1.0, 2.0, 3.0])
b = 2.0
a * b
Out[56]:
array([2., 4., 6.])

Результат получился тем же, поскольку в данном случае произошло растяжение массива b до размеров массива a с помощью дублирования элементов массива b.

broadcasting_1.png

Примечание. Термин "растяжение" используется лишь для понимания. Операции реализуются более "умным" способом без лишнего копирования элементов.

Правило бродкастинга

При работе с двумя массивами numpy сравнивает их формы начиная с крайних правых размерностей. Два измерения совместимы, если

  • они равны или
  • одна из них равна 1. Если эти условия не выполняются, возникает ValueError.

Посмотрим еще на пример

In [57]:
a = np.array([[ 0.0,  0.0,  0.0],
           [10.0, 10.0, 10.0],
           [20.0, 20.0, 20.0],
           [30.0, 30.0, 30.0]])
b = np.array([1.0, 2.0, 3.0])
a + b
Out[57]:
array([[ 1.,  2.,  3.],
       [11., 12., 13.],
       [21., 22., 23.],
       [31., 32., 33.]])

Растяжение в данном случае произошло следующим образом broadcasting_2.png

А если размеры будут не совместимы, то произойдет ошибка broadcasting_3.png

In [58]:
b = np.array([1.0, 2.0, 3.0, 4.0])
a + b
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-58-a441300a98f7> in <module>
      1 b = np.array([1.0, 2.0, 3.0, 4.0])
----> 2 a + b

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

Если массивы имеют несовместимый размер, можно их сначала привести к одной форме

In [59]:
a = np.array([0.0, 10.0, 20.0, 30.0])
b = np.array([1.0, 2.0, 3.0])
a.reshape((-1, 1)) + b
Out[59]:
array([[ 1.,  2.,  3.],
       [11., 12., 13.],
       [21., 22., 23.],
       [31., 32., 33.]])

Соответствующее растяжение broadcasting_4.png

4. Matplotlib

Модуль matplotlib — одно из популярных средств для построения графиков. При использовании matplotlib не забудьте написать %matplotlib inline для того, чтобы графики отображались в вашем окне браузера.

Начнём с построения простых графиков.

In [60]:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

%matplotlib inline

График, соединяющий точки, строится с помощью plt.plot. Передаём список $x$ и $y$. Если не хотите соединять точки, используйте plt.scatter.

In [61]:
plt.figure()
plt.plot([0, 0.25, 1], [0, 1, 0.5])
plt.scatter([0.25, 0.75, 1], [0, 0.5, 1])
plt.show()

Можно изображать несколько кривых, тогда они будут рисоваться разными цветами. Чтобы рисовать график функции, достаточно соединить много точек.

In [62]:
x = np.linspace(0, 2, 100)

plt.figure()
plt.plot(x, x)
plt.plot(x, x**2)
plt.plot(x, x**3)
plt.show()

На график можно добавить подписи, легенду, настроить цвета и стиль линий.

In [63]:
x = np.linspace(-2, 2, 100)

plt.figure(figsize=(8, 8))
plt.plot(x, x ** 2, linestyle='--', lw=3, 
         label='$y=x^2$', color='red')
plt.xlabel('Ось X'), plt.ylabel('Ось Y')
plt.legend(fontsize=15, loc=3)
plt.title('Парабола')
plt.grid(ls=':')
plt.show()

Закрасить область между двумя кривыми $y=y(x)$ можно с помощью функции plt.fill_between, а между двумя кривыми вида $x = x(y)$ --- с помощью функции plt.fill_betweenx.

Горизонтальные линии можно нарисовать с помощью plt.hlines, а вертикальные --- с помощью plt.vlines.

In [64]:
x = np.linspace(-10, 10, 100)

plt.figure(figsize=(12, 7))
plt.fill_between(x, -x+np.sin(x), x+np.sin(x), alpha=0.5)
plt.hlines([-10, -11, -12], -10, 10)
plt.xlabel('Ось X')
plt.ylabel('Ось Y')
plt.grid(ls=':')
plt.show()

Кроме графиков в двумерных координатах, matplotlib позволяет строить трёхмерные графики или поверхности.

In [65]:
X = 10
N = 50
u = np.linspace(-X, X, N)
x, y = np.meshgrid(u, u)
r = np.sqrt(x ** 2 + y ** 2)
z = np.sin(r) / r
In [66]:
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap='gnuplot')
plt.show()

Чтобы посмотреть, как ещё можно настраивать графики в matplotlib, строить контурные графики и делать пиксельные картинки, можете перейти к полному материалу.