Поиск…
Вступление
N-мерные массивы или ndarrays
являются основным объектом numpy, который используется для хранения элементов одного и того же типа данных. Они обеспечивают эффективную структуру данных, превосходящую обычные массивы Python.
замечания
По возможности вырабатывайте операции с данными в терминах массивов и векторных операций. Операции с вектором выполняются намного быстрее, чем эквивалент для циклов
Создать массив
Пустой массив
np.empty((2,3))
Обратите внимание, что в этом случае значения в этом массиве не заданы. Таким образом, создание массива полезно только тогда, когда массив заполняется позже в коде.
Из списка
np.array([0,1,2,3])
# Out: array([0, 1, 2, 3])
Создать диапазон
np.arange(4)
# Out: array([0, 1, 2, 3])
Создать нули
np.zeros((3,2))
# Out:
# array([[ 0., 0.],
# [ 0., 0.],
# [ 0., 0.]])
Создать
np.ones((3,2))
# Out:
# array([[ 1., 1.],
# [ 1., 1.],
# [ 1., 1.]])
Создание элементов массива с линейным интервалом
np.linspace(0,1,21)
# Out:
# array([ 0. , 0.05, 0.1 , 0.15, 0.2 , 0.25, 0.3 , 0.35, 0.4 ,
# 0.45, 0.5 , 0.55, 0.6 , 0.65, 0.7 , 0.75, 0.8 , 0.85,
# 0.9 , 0.95, 1. ])
Создание элементов массива с разбиением на лог
np.logspace(-2,2,5)
# Out:
# array([ 1.00000000e-02, 1.00000000e-01, 1.00000000e+00,
# 1.00000000e+01, 1.00000000e+02])
Создать массив из заданной функции
np.fromfunction(lambda i: i**2, (5,))
# Out:
# array([ 0., 1., 4., 9., 16.])
np.fromfunction(lambda i,j: i**2, (3,3))
# Out:
# array([[ 0., 0., 0.],
# [ 1., 1., 1.],
# [ 4., 4., 4.]])
Операторы массива
x = np.arange(4)
x
#Out:array([0, 1, 2, 3])
скалярное добавление является элементарным
x+10
#Out: array([10, 11, 12, 13])
скалярное умножение является элементарным
x*2
#Out: array([0, 2, 4, 6])
добавление массива является элементарным
x+x
#Out: array([0, 2, 4, 6])
умножение массива является элементарным
x*x
#Out: array([0, 1, 4, 9])
dot (или, в более общем случае, матричное умножение) выполняется с помощью функции
x.dot(x)
#Out: 14
В Python 3.5 оператор @
был добавлен как оператор инфикса для матричного умножения
x = np.diag(np.arange(4))
print(x)
'''
Out: array([[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 2, 0],
[0, 0, 0, 3]])
'''
print(x@x)
print(x)
'''
Out: array([[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 4, 0],
[0, 0, 0, 9]])
'''
Добавить . Возвращает копию с добавленными значениями. НЕ на месте.
#np.append(array, values_to_append, axis=None)
x = np.array([0,1,2,3,4])
np.append(x, [5,6,7,8,9])
# Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
x
# Out: array([0, 1, 2, 3, 4])
y = np.append(x, [5,6,7,8,9])
y
# Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
hstack . Горизонтальный стек. (столбец столбцов)
vstack . Вертикальный стек. (строка строк)
# np.hstack(tup), np.vstack(tup)
x = np.array([0,0,0])
y = np.array([1,1,1])
z = np.array([2,2,2])
np.hstack(x,y,z)
# Out: array([0, 0, 0, 1, 1, 1, 2, 2, 2])
np.vstack(x,y,z)
# Out: array([[0, 0, 0],
# [1, 1, 1],
# [2, 2, 2]])
Доступ к массиву
Синтаксис Slice - это i:j:k
где i
- начальный индекс (включительно), j
- индекс остановки (исключение), а k
- размер шага. Как и другие структуры данных python, первый элемент имеет индекс 0:
x = np.arange(10)
x[0]
# Out: 0
x[0:4]
# Out: array([0, 1, 2, 3])
x[0:4:2]
# Out:array([0, 2])
Отрицательные значения рассчитываются с конца массива. -1
поэтому обращается к последнему элементу массива:
x[-1]
# Out: 9
x[-1:0:-1]
# Out: array([9, 8, 7, 6, 5, 4, 3, 2, 1])
Доступ к многомерным массивам можно получить, указав каждое измерение, разделенное запятыми. Все предыдущие правила применяются.
x = np.arange(16).reshape((4,4))
x
# Out:
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11],
# [12, 13, 14, 15]])
x[1,1]
# Out: 5
x[0:3,0]
# Out: array([0, 4, 8])
x[0:3, 0:3]
# Out:
# array([[ 0, 1, 2],
# [ 4, 5, 6],
# [ 8, 9, 10]])
x[0:3:2, 0:3:2]
# Out:
# array([[ 0, 2],
# [ 8, 10]])
Транспонирование массива
arr = np.arange(10).reshape(2, 5)
Использование метода .transpose
:
arr.transpose()
# Out:
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])
.T
:
arr.T
# Out:
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])
Или np.transpose
:
np.transpose(arr)
# Out:
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])
В случае двумерного массива это эквивалентно стандартной матричной транспозиции (как показано выше). В n-мерном случае вы можете указать перестановку осей массива. По умолчанию это отменяет array.shape
:
a = np.arange(12).reshape((3,2,2))
a.transpose() # equivalent to a.transpose(2,1,0)
# Out:
# array([[[ 0, 4, 8],
# [ 2, 6, 10]],
#
# [[ 1, 5, 9],
# [ 3, 7, 11]]])
Но возможна любая перестановка индексов осей:
a.transpose(2,0,1)
# Out:
# array([[[ 0, 2],
# [ 4, 6],
# [ 8, 10]],
#
# [[ 1, 3],
# [ 5, 7],
# [ 9, 11]]])
a = np.arange(24).reshape((2,3,4)) # shape (2,3,4)
a.transpose(2,0,1).shape
# Out:
# (4, 2, 3)
Булевское индексирование
arr = np.arange(7)
print(arr)
# Out: array([0, 1, 2, 3, 4, 5, 6])
Сравнение со скаляром возвращает логический массив:
arr > 4
# Out: array([False, False, False, False, False, True, True], dtype=bool)
Этот массив можно использовать для индексирования, чтобы выбрать только числа больше 4:
arr[arr>4]
# Out: array([5, 6])
Булевое индексирование может использоваться между различными массивами (например, связанные параллельные массивы):
# Two related arrays of same length, i.e. parallel arrays
idxs = np.arange(10)
sqrs = idxs**2
# Retrieve elements from one array using a condition on the other
my_sqrs = sqrs[idxs % 2 == 0]
print(my_sqrs)
# Out: array([0, 4, 16, 36, 64])
Изменение формы массива
Метод numpy.reshape
(такой же, как numpy.ndarray.reshape
) возвращает массив того же общего размера, но в новой форме:
print(np.arange(10).reshape((2, 5)))
# [[0 1 2 3 4]
# [5 6 7 8 9]]
Он возвращает новый массив и не работает на месте:
a = np.arange(12)
a.reshape((3, 4))
print(a)
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
Тем не менее, можно перезаписать shape
атрибут ndarray
:
a = np.arange(12)
a.shape = (3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
Сначала это поведение может быть неожиданным, но ndarray
s хранятся в смежных блоках памяти, и их shape
определяет только то, как этот поток данных следует интерпретировать как многомерный объект.
До одной оси в корте shape
может иметь значение -1
. Затем numpy
выведет длину этой оси для вас:
a = np.arange(12)
print(a.reshape((3, -1)))
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
Или же:
a = np.arange(12)
print(a.reshape((3, 2, -1)))
# [[[ 0 1]
# [ 2 3]]
# [[ 4 5]
# [ 6 7]]
# [[ 8 9]
# [10 11]]]
Множественные неопределенные измерения, например a.reshape((3, -1, -1))
, не допускаются и будут ValueError
.
Операции вещательного массива
Арифметические операции выполняются по элементам на массивах Numpy. Для массивов одинаковой формы это означает, что операция выполняется между элементами с соответствующими индексами.
# Create two arrays of the same size
a = np.arange(6).reshape(2, 3)
b = np.ones(6).reshape(2, 3)
a
# array([0, 1, 2],
# [3, 4, 5])
b
# array([1, 1, 1],
# [1, 1, 1])
# a + b: a and b are added elementwise
a + b
# array([1, 2, 3],
# [4, 5, 6])
Арифметические операции могут также выполняться на массивах разной формы с помощью широковещательной передачи Numpy. В общем, один массив «передается» по другому, так что поэлементные операции выполняются на под-массивах конгруэнтной формы.
# Create arrays of shapes (1, 5) and (13, 1) respectively
a = np.arange(5).reshape(1, 5)
a
# array([[0, 1, 2, 3, 4]])
b = np.arange(4).reshape(4, 1)
b
# array([0],
# [1],
# [2],
# [3])
# When multiplying a * b, slices with the same dimensions are multiplied
# elementwise. In the case of a * b, the one and only row of a is multiplied
# with each scalar down the one and only column of b.
a*b
# array([[ 0, 0, 0, 0, 0],
# [ 0, 1, 2, 3, 4],
# [ 0, 2, 4, 6, 8],
# [ 0, 3, 6, 9, 12]])
Чтобы проиллюстрировать это далее, рассмотрим умножение двумерных и трехмерных массивов с конгруэнтными субразмерами.
# Create arrays of shapes (2, 2, 3) and (2, 3) respectively
a = np.arange(12).reshape(2, 2, 3)
a
# array([[[ 0 1 2]
# [ 3 4 5]]
#
# [[ 6 7 8]
# [ 9 10 11]]])
b = np.arange(6).reshape(2, 3)
# array([[0, 1, 2],
# [3, 4, 5]])
# Executing a*b broadcasts b to each (2, 3) slice of a,
# multiplying elementwise.
a*b
# array([[[ 0, 1, 4],
# [ 9, 16, 25]],
#
# [[ 0, 7, 16],
# [27, 40, 55]]])
# Executing b*a gives the same result, i.e. the smaller
# array is broadcast over the other.
Когда применяется широковещательная передача массива?
Вещание происходит, когда два массива имеют совместимые формы.
Формы сравниваются по компонентам, начиная с конечных. Два измерения совместимы, если они одинаковы или один из них равен 1
. Если одна форма имеет более высокий размер, чем другой, то превосходящие компоненты не сравниваются.
Некоторые примеры совместимых форм:
(7, 5, 3) # compatible because dimensions are the same
(7, 5, 3)
(7, 5, 3) # compatible because second dimension is 1
(7, 1, 3)
(7, 5, 3, 5) # compatible because exceeding dimensions are not compared
(3, 5)
(3, 4, 5) # incompatible
(5, 5)
(3, 4, 5) # compatible
(1, 5)
Вот официальная документация по широковещанию массивов .
Заполнение массива содержимым файла CSV
filePath = "file.csv"
data = np.genfromtxt(filePath)
Многие варианты поддерживаются, см. Официальную документацию для полного списка:
data = np.genfromtxt(filePath, dtype='float', delimiter=';', skip_header=1, usecols=(0,1,3) )
Нумерометр n-мерного массива: ndarray
Основной структурой данных в numpy является ndarray
(сокращение от n- мерного массива). ndarray
s
- однородные (т.е. они содержат элементы одного и того же типа данных)
- содержат элементы фиксированных размеров (заданные формой , кортеж из n положительных целых чисел, которые определяют размеры каждого измерения)
Одномерный массив:
x = np.arange(15)
# array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
x.shape
# (15,)
Двумерный массив:
x = np.asarray([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])
x
# array([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14]])
x.shape
# (3, 5)
Трехмерная:
np.arange(12).reshape([2,3,2])
Для инициализации массива без указания его содержимого используйте:
x = np.empty([2, 2])
# array([[ 0., 0.],
# [ 0., 0.]])
Догадка типа данных и автоматическое литье
Тип данных установлен как плавающий по умолчанию
x = np.empty([2, 2])
# array([[ 0., 0.],
# [ 0., 0.]])
x.dtype
# dtype('float64')
Если предоставлены некоторые данные, numpy угадает тип данных:
x = np.asarray([[1, 2], [3, 4]])
x.dtype
# dtype('int32')
Обратите внимание: при выполнении присвоений numpy попытается автоматически ndarray
значения в соответствии с ndarray
данных ndarray
x[1, 1] = 1.5 # assign a float value
x[1, 1]
# 1
# value has been casted to int
x[1, 1] = 'z' # value cannot be casted, resulting in a ValueError
Передача массивов
См. Также операции массива вещания .
x = np.asarray([[1, 2], [3, 4]])
# array([[1, 2],
[3, 4]])
y = np.asarray([[5, 6]])
# array([[5, 6]])
В матричной терминологии мы будем иметь матрицу 2x2 и вектор строки 1x2. Тем не менее мы можем сделать сумму
# x + y
array([[ 6, 8],
[ 8, 10]])
Это связано с тем, что массив y
« растянут » до:
array([[5, 6],
[5, 6]])
в соответствии с формой x
.
Ресурсы:
- Введение в ndarray из официальной документации: N-мерный массив (ndarray)
- Ссылка на класс: ndarray .