Матрицы и массивы NumPy в Python
NumPy хранит матрицу в объекте ndarray и задает ее форму парой чисел — числом строк и числом столбцов. Несовпадение форм (shape) при поэлементных операциях — сложении, умножении * — вызывает ошибку трансляции (broadcasting), и NumPy прямо называет, какие формы разошлись.
В статье — создание двумерного массива NumPy, его форма и broadcasting, сложение, умножение и транспонирование матриц, обратная матрица, доступ к элементам, строкам, столбцам и срезам, а также добавление элементов через np.append. Каждый пример — рабочий код на Python с выводом ровно таким, каким его печатает интерпретатор.
Матрицы в Python
Python не имеет встроенного типа данных для матриц, но список из списков работает как матрица. Например:
A = [[1, 4, 5],
[-5, 8, 9]]
Такой список задает матрицу на 2 строки и 3 столбца.

Справка по спискам Python — в официальной документации.
Давайте посмотрим, как работать с вложенным списком.
A = [[1, 4, 5, 12],
[-5, 8, 9, 0],
[-6, 7, 11, 19]]
print("A =", A)
print("A[1] =", A[1]) # вторая строка
print("A[1][2] =", A[1][2]) # третий элемент второй строки
print("A[0][-1] =", A[0][-1]) # последний элемент первой строки
column = [] # пустой список
for row in A:
column.append(row[2])
print("3-й столбец =", column)
Когда мы запустим эту программу, результат будет следующий:
A = [[1, 4, 5, 12], [-5, 8, 9, 0], [-6, 7, 11, 19]]
A[1] = [-5, 8, 9, 0]
A[1][2] = 9
A[0][-1] = 12
3-й столбец = [5, 9, 11]
Вложенные списки подходят для простых вычислительных задач. Но в Python есть более эффективный способ работы с матрицами — NumPy.
Как установить NumPy в Python и создать первый массив
NumPy — библиотека для научных вычислений на Python с мощным объектом N-мерного массива. Поставьте ее командой:
pip install numpyПроверьте версию после установки:
import numpy
print(numpy.__version__)
Команда напечатает установленную версию в формате X.Y.Z, например 1.26.0.
- Подробный разбор способов установки — официальная страница установки NumPy.
- На Windows подходит и дистрибутив anaconda: он ставит NumPy вместе с другими библиотеками для анализа данных.
После установки NumPy можно импортировать и использовать в коде.
Вывод в примерах статьи — из свежей версии NumPy. В старых версиях мелкие детали формата чисел (отступы, число знаков после точки) могут отличаться, а сама логика операций — нет.
NumPy хранит числа в объекте ndarray — многомерном массиве. Рассмотрим пример:
import numpy as np
a = np.array([1, 2, 3])
print(a) # Вывод: [1 2 3]
print(type(a)) # Вывод: <class 'numpy.ndarray'>
Как видите, класс массива NumPy называется ndarray.
Как создать массив NumPy?
Существует несколько способов создания массивов NumPy.
Массив целых чисел, чисел с плавающей точкой и комплексных чисел
import numpy as np
A = np.array([[1, 2, 3], [3, 4, 5]])
print(A)
A = np.array([[1.1, 2, 3], [3, 4, 5]]) # Массив чисел с плавающей запятой
print(A)
A = np.array([[1, 2, 3], [3, 4, 5]], dtype = complex) # Массив комплексных чисел
print(A)
Когда вы запустите эту программу, результат будет следующий:
[[1 2 3]
[3 4 5]]
[[1.1 2. 3. ]
[3. 4. 5. ]]
[[1.+0.j 2.+0.j 3.+0.j]
[3.+0.j 4.+0.j 5.+0.j]]
Массив нулей и единиц
import numpy as np
zeros_array = np.zeros( (2, 3) )
print(zeros_array)
'''
Вывод:
[[0. 0. 0.]
[0. 0. 0.]]
'''
ones_array = np.ones( (1, 5), dtype=np.int32 ) # указание dtype
print(ones_array) # Вывод: [[1 1 1 1 1]]
Здесь мы указали dtype — 32 бита (4 байта). Следовательно, этот массив может принимать значения от -231 до 231-1, то есть от -2 147 483 648 до 2 147 483 647.
Единичная матрица NumPy
Единичная матрица — квадратная матрица с единицами на главной диагонали и нулями на остальных местах. Собирают ее функции numpy.eye или numpy.identity:
import numpy as np
I = np.eye(3)
print(I)
# Вывод:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
numpy.identity(3) дает тот же результат. numpy.eye берут, когда матрица не квадратная или единицы нужны не строго по главной диагонали.
Использование arange(), shape и broadcasting
import numpy as np
A = np.arange(4)
print('A =', A)
B = np.arange(12).reshape(2, 6)
print('B =', B)
'''
Вывод:
A = [0 1 2 3]
B = [[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
'''
У каждого массива есть атрибут shape — кортеж с числом элементов по каждой оси:
print(B.shape)
# Вывод:
# (2, 6)
При арифметике NumPy сравнивает shape операндов и растягивает (транслирует, broadcast) меньший массив под больший, если размеры совпадают или один из них равен 1. Так вектор из трех чисел складывается с каждой строкой матрицы 2×3 без цикла:
import numpy as np
matrix = np.array([[1, 2, 3], [4, 5, 6]])
row = np.array([10, 20, 30])
print(matrix + row)
# Вывод:
# [[11 22 33]
# [14 25 36]]
Если формы несовместимы, NumPy не подбирает значения сам, а останавливается с ошибкой трансляции:
import numpy as np
matrix = np.array([[1, 2, 3], [4, 5, 6]])
pair = np.array([1, 2])
print(matrix + pair)
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
Ошибка называет обе формы: (2, 3) у matrix и (2,) у pair. Число строк совпадает, а число столбцов и элементов — нет, поэтому транслировать pair под каждую строку matrix нельзя: форму нужно привести к (3,) или к (2, 1).
Узнайте больше о других способах создания массива NumPy.
Операции с матрицами
Вложенные списки годятся для одной операции, но с ростом матрицы код разрастается — под каждую операцию нужен свой цикл. NumPy выполняет ту же задачу одной командой: рассмотрим сложение, умножение, транспонирование и обратную матрицу.
Сложение двух матриц или сумма элементов массива Python
Мы используем оператор +, чтобы сложить соответствующие элементы двух матриц NumPy.
import numpy as np
A = np.array([[2, 4], [5, -6]])
B = np.array([[9, -3], [3, 6]])
C = A + B # сложение соответствующих элементов
print(C)
'''
Вывод:
[[11 1]
[ 8 0]]
'''
Функция numpy.sum считает сумму элементов массива — всех сразу или по одной оси через параметр axis: axis=0 — сумма по столбцам, axis=1 — сумма по строкам.
import numpy as np
A = np.array([[2, 4], [5, -6]])
print(A.sum()) # сумма всех элементов
print(A.sum(axis=0)) # сумма по столбцам
print(A.sum(axis=1)) # сумма по строкам
# Вывод:
# 5
# [ 7 -2]
# [ 6 -1]
Умножение двух матриц Python
Чтобы умножить две матрицы, мы используем метод dot(). Узнайте больше о том, как работает numpy.dot.
Примечание: * используется для умножения массива (умножения соответствующих элементов двух массивов), а не умножения матрицы.
import numpy as np
A = np.array([[3, 6, 7], [5, -3, 0]])
B = np.array([[1, 1], [2, 1], [3, -3]])
C = A.dot(B)
print(C)
'''
Вывод:
[[ 36 -12]
[ -1 2]]
'''
Начиная с Python 3.5 то же умножение записывают оператором @ — это более короткая запись A.dot(B):
print(A @ B)
# Вывод:
# [[ 36 -12]
# [ -1 2]]
Транспонирование матрицы Python
Мы используем numpy.transpose для вычисления транспонирования матрицы.
import numpy as np
A = np.array([[1, 1], [2, 1], [3, -3]])
print(A.transpose())
'''
Вывод:
[[ 1 2 3]
[ 1 1 -3]]
'''
Как видите, NumPy значительно упростил нашу задачу.
Обратная матрица NumPy
NumPy вычисляет обратную матрицу функцией numpy.linalg.inv: произведение матрицы на обратную дает единичную матрицу.
import numpy as np
A = np.array([[4, 7], [2, 6]])
A_inv = np.linalg.inv(A)
print(A_inv)
# Вывод:
# [[ 0.6 -0.7]
# [-0.2 0.4]]
Обратная матрица существует только у квадратной матрицы с ненулевым определителем. У вырожденной матрицы (определитель равен нулю) numpy.linalg.inv останавливается с ошибкой numpy.linalg.LinAlgError: Singular matrix — обратной у такой матрицы нет.
Доступ к элементам матрицы, строкам и столбцам
Доступ к элементам матрицы
Также можно получить доступ к элементам матрицы, используя индекс. Начнем с одномерного массива NumPy.
import numpy as np
A = np.array([2, 4, 6, 8, 10])
print("A[0] =", A[0]) # Первый элемент
print("A[2] =", A[2]) # Третий элемент
print("A[-1] =", A[-1]) # Последний элемент
Когда вы запустите эту программу, результат будет следующий:
A[0] = 2
A[2] = 6
A[-1] = 10
Теперь выясним, как получить доступ к элементам двумерного массива (который в основном представляет собой матрицу).
import numpy as np
A = np.array([[1, 4, 5, 12],
[-5, 8, 9, 0],
[-6, 7, 11, 19]])
# Первый элемент первой строки
print("A[0][0] =", A[0][0])
# Третий элемент второй строки
print("A[1][2] =", A[1][2])
# Последний элемент последней строки
print("A[-1][-1] =", A[-1][-1])
Когда мы запустим эту программу, результат будет следующий:
A[0][0] = 1
A[1][2] = 9
A[-1][-1] = 19
Доступ к строкам матрицы
import numpy as np
A = np.array([[1, 4, 5, 12],
[-5, 8, 9, 0],
[-6, 7, 11, 19]])
print("A[0] =", A[0]) # Первая строка
print("A[2] =", A[2]) # Третья строка
print("A[-1] =", A[-1]) # Последняя строка (третья строка в данном случае)
Когда мы запустим эту программу, результат будет следующий:
A[0] = [ 1 4 5 12]
A[2] = [-6 7 11 19]
A[-1] = [-6 7 11 19]
Доступ к столбцам матрицы
import numpy as np
A = np.array([[1, 4, 5, 12],
[-5, 8, 9, 0],
[-6, 7, 11, 19]])
print("A[:, 0] =", A[:, 0]) # Первый столбец
print("A[:, 3] =", A[:, 3]) # Четвёртый столбец
print("A[:, -1] =", A[:, -1]) # Последний столбец (четвёртый столбец в данном случае)
Когда мы запустим эту программу, результат будет следующий:
A[:, 0] = [ 1 -5 -6]
A[:, 3] = [12 0 19]
A[:, -1] = [12 0 19]
Если вы не знаете, как работает приведенный выше код, прочтите раздел «Срезы (slicing) матрицы».
Срезы (slicing) матрицы
Срез одномерного массива NumPy работает как срез списка. Рассмотрим пример:
import numpy as np
numbers = np.array([1, 3, 5, 7, 9, 7, 5])
# с 3-го по 5-й элементы
print(numbers[2:5]) # Вывод: [5 7 9]
# с 1-го по 2-й элементы
print(numbers[:-5]) # Вывод: [1 3]
# с 6-го до последнего элемента
print(numbers[5:]) # Вывод: [7 5]
# весь массив
print(numbers[:]) # Вывод: [1 3 5 7 9 7 5]
# массив в обратном порядке
print(numbers[::-1]) # Вывод: [5 7 9 7 5 3 1]
Теперь посмотрим, как сделать срез матрицы.
import numpy as np
A = np.array([[1, 4, 5, 12, 14],
[-5, 8, 9, 0, 17],
[-6, 7, 11, 19, 21]])
print(A[:2, :4]) # две строки, четыре столбца
''' Вывод:
[[ 1 4 5 12]
[-5 8 9 0]]
'''
print(A[:1,]) # первая строка, все столбцы
''' Вывод:
[[ 1 4 5 12 14]]
'''
print(A[:,2]) # все строки, третий столбец
''' Вывод:
[ 5 9 11]
'''
print(A[:, 2:5]) # все строки, с третьего по пятый столбец
''' Вывод:
[[ 5 12 14]
[ 9 0 17]
[11 19 21]]
'''
Добавление элементов: np.append()
Функция numpy.append добавляет элементы в конец массива и возвращает новый массив — исходный она не меняет.
import numpy as np
A = np.array([1, 2, 3])
B = np.append(A, [4, 5])
print(B)
print(A)
# Вывод:
# [1 2 3 4 5]
# [1 2 3]
Также можно добавить строку в двумерный массив — через параметр axis; формы массивов должны совпадать по остальным осям:
import numpy as np
C = np.array([[1, 2], [3, 4]])
D = np.append(C, [[5, 6]], axis=0)
print(D)
# Вывод:
# [[1 2]
# [3 4]
# [5 6]]
Каждый вызов numpy.append копирует весь массив: для разового добавления это нормально, а в цикле — дороже, чем собрать список и один раз обернуть его в numpy.array.
Использование NumPy вместо вложенных списков значительно упрощает работу с матрицами. Изучите пакет NumPy подробнее, если планируете использовать Python для анализа данных.
Комментарии
Почему в срезе используете запятую, у меня выдаёт ошибку:-(