Авторы материала: программист-исследователь Mail.ru Group, старший преподаватель Факультета Компьютерных Наук ВШЭ Юрий Кашницкий и Data Scientist в Segmento Екатерина Демидова. Материал распространяется на условиях лицензии Creative Commons CC BY-NC-SA 4.0. Можно использовать в любых целях (редактировать, поправлять и брать за основу), кроме коммерческих, но с обязательным упоминанием автора материала.
Numpy - это библиотека Python для вычислительно эффективных операций с многомерными массивами, предназначенная в основном для научных вычислений.
In [1]:
# Python 2 and 3 compatibility
from __future__ import (absolute_import, division,
print_function, unicode_literals)
# отключим предупреждения Anaconda
import warnings
warnings.simplefilter('ignore')
import numpy as np
In [2]:
a = np.array([0, 1, 2, 3])
a
Out[2]:
Такой массив может содержать:
Зачем NumPy: Эффективность базовых операций
In [3]:
L = range(1000)
In [4]:
%timeit [i**2 for i in L]
In [5]:
a = np.arange(1000)
In [6]:
%timeit a**2
Интерактивная справка
In [7]:
?np.array
поиск в документации
In [8]:
np.lookfor('create array')
In [9]:
np.con*?
In [10]:
import numpy as np
In [11]:
a = np.array([0, 1, 2, 3])
a
Out[11]:
In [12]:
a.ndim
Out[12]:
In [13]:
a.shape
Out[13]:
In [14]:
len(a)
Out[14]:
In [15]:
b = np.array([[0, 1, 2], [3, 4, 5]]) # 2 x 3 array
b
Out[15]:
In [16]:
b.ndim
Out[16]:
In [17]:
b.shape
Out[17]:
In [18]:
len(b) # returns the size of the first dimension
Out[18]:
In [19]:
c = np.array([[[1], [2]], [[3], [4]]])
c
Out[19]:
In [20]:
c.shape
Out[20]:
На практике мы редко добавляем элементы по одному
In [21]:
a = np.arange(10) # 0 .. n-1 (!)
a
Out[21]:
In [22]:
b = np.arange(1, 9, 2) # start, end (exclusive), step
b
Out[22]:
In [23]:
c = np.linspace(0, 1, 6) # start, end, num-points
c
Out[23]:
In [24]:
d = np.linspace(0, 1, 5, endpoint=False)
d
Out[24]:
In [25]:
a = np.ones((3, 3)) # reminder: (3, 3) is a tuple
a
Out[25]:
In [26]:
b = np.zeros((2, 2))
b
Out[26]:
In [27]:
c = np.eye(3)
c
Out[27]:
In [28]:
d = np.diag(np.array([1, 2, 3, 4]))
d
Out[28]:
np.random
генерация случайных чисел (Mersenne Twister PRNG):
In [29]:
a = np.random.rand(4) # uniform in [0, 1]
a
Out[29]:
In [30]:
b = np.random.randn(4) # Gaussian
b
Out[30]:
In [31]:
np.random.seed(1234) # Setting the random seed
Точка после числа означает, что это тип данных float64
In [32]:
a = np.array([1, 2, 3])
a.dtype
Out[32]:
In [33]:
b = np.array([1., 2., 3.])
b.dtype
Out[33]:
Можно задать тип данных явно. По умолчанию - float64
In [34]:
c = np.array([1, 2, 3], dtype=float)
c.dtype
Out[34]:
In [35]:
a = np.ones((3, 3))
a.dtype
Out[35]:
Прочие типы данных:
In [36]:
d = np.array([1+2j, 3+4j, 5+6*1j])
d.dtype
Out[36]:
In [37]:
e = np.array([True, False, False, True])
e.dtype
Out[37]:
На строки память выделяется "жадно" - по максимальному числу литер в строке. В этом примере на каждую строку выделяется по 7 литер, и тип данных - 'S7'
In [38]:
f = np.array(['Bonjour', 'Hello', 'Hallo',])
f.dtype # <--- strings containing max. 7 letters
Out[38]:
$ ipython notebook --pylab=inline
Или из тетрадки:
In [39]:
%pylab inline
Параметр inline
говорит серверу IPython о том, что результаты будут отображаться в самой тетрадке, а не в новом окне.
Импортируем Matplotlib
In [40]:
import matplotlib.pyplot as plt # the tidy way
In [41]:
x = np.linspace(0, 3, 20)
y = np.linspace(0, 9, 20)
plt.plot(x, y) # line plot
plt.show() # <-- shows the plot (not needed with pylab)
Или с использованием pylab:
In [42]:
plot(x, y) # line plot
Out[42]:
Использование import matplotlib.pyplot as plt
рекомендуется для скриптов, а pylab
- в тетрадках IPython.
In [43]:
x = np.linspace(0, 3, 20)
y = np.linspace(0, 9, 20)
plt.plot(x, y) # line plot
Out[43]:
In [44]:
plt.plot(x, y, 'o') # dot plot
Out[44]:
In [45]:
image = np.random.rand(30, 30)
plt.imshow(image, cmap=plt.cm.hot)
plt.colorbar()
Out[45]:
В целом так же, как со встроенными последовательностями Python (например, как со списками).
In [46]:
a = np.arange(10)
a
Out[46]:
In [47]:
a[0], a[2], a[-1]
Out[47]:
Работает и популярный в Python способ отражения массива:
In [48]:
a[::-1]
Out[48]:
Для многомерных массивов индексы - это кортежи целых чисел
In [49]:
a = np.diag(np.arange(3))
a
Out[49]:
In [50]:
a[1, 1]
Out[50]:
In [51]:
a[2, 1] = 10 # third line, second column
a
Out[51]:
In [52]:
a[1]
Out[52]:
Срезы
In [53]:
a = np.arange(10)
a
Out[53]:
In [54]:
a[2:9:3] # [start:end:step]
Out[54]:
Последний индекс не включается
In [55]:
a[:4]
Out[55]:
По умолчанию `start` - 0, `end` - индекс последнего элемента, `step` - 1:
In [56]:
a[1:3]
Out[56]:
In [57]:
a[::2]
Out[57]:
In [58]:
a[3:]
Out[58]:
Можно совмещать присваивание и срез:
In [59]:
a = np.arange(10)
a[5:] = 10
a
Out[59]:
In [60]:
b = np.arange(5)
a[5:] = b[::-1]
a
Out[60]:
Отобразить матрицу, в которой вычеркивается (x, y), если y делится на x.
In [61]:
from IPython.display import Image
Image(filename='../img/prime-sieve.png')
Out[61]:
is_prime
, заполненний значениями True
In [62]:
is_prime = np.ones((100,), dtype=bool)
In [63]:
is_prime[:2] = 0
j
начиная с 2, "вычеркнем" числа, ему кратные:
In [64]:
N_max = int(np.sqrt(len(is_prime)))
for j in range(2, N_max):
is_prime[2*j::j] = False
is_prime
Out[64]:
In [65]:
np.random.seed(3)
a = np.random.random_integers(0, 20, 15)
a
Out[65]:
In [66]:
(a % 3 == 0)
Out[66]:
In [67]:
mask = (a % 3 == 0)
extract_from_a = a[mask] # or, a[a%3==0]
extract_from_a # extract a sub-array with the mask
Out[67]:
Индексирование маской может быть очень полезным для присваивания значений части элементов массива:
In [68]:
a[a % 3 == 0] = -1
a
Out[68]:
In [69]:
a = np.arange(0, 100, 10)
a
Out[69]:
In [70]:
a[[2, 3, 2, 4, 2]] # note: [2, 3, 2, 4, 2] is a Python list
Out[70]:
In [71]:
a[[9, 7]] = -100
a
Out[71]:
In [72]:
a = np.arange(10)
idx = np.array([[3, 4], [9, 7]])
idx.shape
Out[72]:
In [73]:
a[idx]
Out[73]: