Основы NumPy на практике индексы, массивы, оси и функции

2070
Основы NumPy на практике индексы, массивы, оси и функции

NumPy помогает хранить числовые данные в многомерных массивах и выполнять вычисления сразу над целыми наборами значений. Вместо циклов Python разработчик применяет операции к массиву, а основную работу выполняет оптимизированный код библиотеки.

Главный объект NumPy называется ndarray. Массив имеет фиксированное число измерений, форму и единый тип элементов. Шпаргалка охватывает установку NumPy, создание массивов, индексацию, фильтрацию, изменение формы, вычисления по осям, случайные числа и сохранение данных.

Примеры рассчитаны на NumPy 2.x. В NumPy 2.5 разработчики отказались от поддержки Python 3.11. Для NumPy 2.5 нужен Python 3.12, 3.13 или 3.14. Большинство базовых примеров также работает в NumPy 1.26 и ранних версиях 2.x.

Содержание

Установка и проверка NumPy

Устанавливайте NumPy через тот же интерпретатор Python, которым запускаете программу. Такой подход снижает риск установить пакет не в то виртуальное окружение.

Windows

py -m pip install --upgrade numpy

Linux и macOS

python3 -m pip install --upgrade numpy

Проверьте установленную версию.

python -c "import numpy as np; print(np.__version__)"

В Windows вместо python может потребоваться команда py.

Импортируйте библиотеку под общепринятым коротким именем np.

import numpy as np

Официальное руководство для начинающих доступно в документации NumPy.

Команда pip install numpy устанавливает последнюю версию, совместимую с текущим Python. Python 3.11 не поддерживает NumPy 2.5. Обновите Python или установите совместимую ветку командой python -m pip install "numpy<2.5".

Создание массивов

Массив из списка Python

a = np.array([10, 20, 30, 40])
 
 matrix = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])

Вложенные списки одинаковой длины образуют двумерный массив.

Явное указание типа

a = np.array([1, 2, 3], dtype=np.float64)
 b = np.array([1, 0, 1], dtype=np.bool_)

Все элементы массива используют один тип. Если передать целые и дробные числа вместе, NumPy обычно приведёт целые значения к дробному типу.

Массивы с готовым заполнением

zeros = np.zeros((2, 3))
 ones = np.ones((2, 3))
 filled = np.full((2, 3), 7)
 identity = np.eye(3)

Полученные значения выглядят так.

zeros
 # array([[0., 0., 0.],
 #        [0., 0., 0.]])
 
 filled
 # array([[7, 7, 7],
 #        [7, 7, 7]])

Пустой массив

a = np.empty((2, 3))

np.empty() не заполняет массив нулями. Функция выделяет память, в которой могут находиться произвольные старые значения. Заполните массив перед чтением или примените np.zeros().

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

a = np.arange(0, 10, 2)
 # array([0, 2, 4, 6, 8])
 
 b = np.linspace(0, 1, 5)
 # array([0.  , 0.25, 0.5 , 0.75, 1.  ])
  • np.arange(start, stop, step) создаёт значения с заданным шагом и не включает границу stop.
  • np.linspace(start, stop, num) создаёт указанное число равномерно распределённых точек и по умолчанию включает обе границы.

Для дробного шага чаще выбирайте np.linspace(). Ошибки представления чисел с плавающей точкой могут сделать результат np.arange() неожиданным.

Массив по образцу

source = np.array([[1, 2], [3, 4]])
 
 a = np.zeros_like(source)
 b = np.ones_like(source)
 c = np.full_like(source, 9)

Функции с окончанием _like копируют форму и тип исходного массива.

Основные свойства массива

a = np.array([
     [10, 20, 30],
     [40, 50, 60]
 ])
 
 print(a.ndim)      # 2
 print(a.shape)     # (2, 3)
 print(a.size)      # 6
 print(a.dtype)     # тип элементов
 print(a.itemsize)  # байт на один элемент
 print(a.nbytes)    # общий размер данных в байтах
Свойство Что показывает
ndim Число измерений массива
shape Размер вдоль каждой оси
size Общее число элементов
dtype Тип элементов
itemsize Размер одного элемента в байтах
nbytes Объём памяти под данные массива

Форма (2, 3) означает две строки и три столбца. Форма одномерного массива из трёх элементов записывается как (3,).

Изменение типа

a = np.array([1, 2, 3])
 b = a.astype(np.float64)
 
 print(b)
 # array([1., 2., 3.])

Преобразование дробных чисел в целые отбрасывает дробную часть. Маленький целочисленный тип также может не вместить исходное значение.

a = np.array([1.9, 2.5, -3.8])
 b = a.astype(np.int64)
 
 print(b)
 # array([ 1,  2, -3])

Индексы и срезы

Одномерный массив

a = np.array([10, 20, 30, 40, 50])
 
 a[0]       # 10
 a[-1]      # 50
 a[1:4]     # array([20, 30, 40])
 a[:3]      # array([10, 20, 30])
 a[::2]     # array([10, 30, 50])
 a[::-1]    # array([50, 40, 30, 20, 10])

Начальная граница среза включается, конечная не включается.

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

a = np.array([
     [10, 20, 30],
     [40, 50, 60],
     [70, 80, 90]
 ])
 
 a[1, 2]      # 60
 a[0]         # первая строка
 a[:, 1]      # второй столбец
 a[0:2, 1:3]  # строки 0 и 1, столбцы 1 и 2

Для двумерного массива сначала указывают индекс строки, затем индекс столбца.

Выбор элементов по списку индексов

a = np.array([10, 20, 30, 40, 50])
 selected = a[[0, 2, 4]]
 
 print(selected)
 # array([10, 30, 50])

Изменение элементов

a = np.array([10, 20, 30, 40])
 
 a[0] = 99
 a[1:3] = 0
 
 print(a)
 # array([99,  0,  0, 40])

Срезы и копии

Обычный срез чаще возвращает представление исходных данных. Изменение среза может изменить исходный массив.

a = np.array([10, 20, 30, 40, 50])
 part = a[1:4]
 
 part[0] = 999
 
 print(a)
 # array([ 10, 999,  30,  40,  50])

Создайте независимый массив через copy().

a = np.array([10, 20, 30, 40, 50])
 part = a[1:4].copy()
 
 part[0] = 999
 
 print(a)
 # array([10, 20, 30, 40, 50])

Выбор по массиву индексов и логической маске обычно создаёт копию. Простые срезы обычно создают представление.

Фильтрация данных

Логическая маска

a = np.array([5, 12, 18, 3, 25])
 
 mask = a > 10
 print(mask)
 # array([False,  True,  True, False,  True])
 
 result = a[mask]
 print(result)
 # array([12, 18, 25])

Несколько условий

a = np.array([5, 12, 18, 3, 25])
 
 result = a[(a >= 10) & (a <= 20)]
 # array([12, 18])
Оператор Действие
& Логическое И
| Логическое ИЛИ
~ Логическое НЕ

Не применяйте Python-операторы and, or и not к массивам. Используйте &, | и ~, а каждое сравнение заключайте в скобки.

Замена по условию

a = np.array([-3, 5, -1, 8])
 
 a[a < 0] = 0
 
 print(a)
 # array([0, 5, 0, 8])

Функция where

a = np.array([5, 12, 18, 3])
 
 result = np.where(a >= 10, "много", "мало")
 
 print(result)
 # array(['мало', 'много', 'много', 'мало'])

np.where() выбирает значение из второго или третьего аргумента для каждого элемента.

Поиск индексов

a = np.array([5, 12, 18, 3])
 
 indices = np.where(a > 10)
 print(indices[0])
 # array([1, 2])

Изменение формы массива

reshape

a = np.arange(12)
 matrix = a.reshape(3, 4)
 
 print(matrix)
 # array([[ 0,  1,  2,  3],
 #        [ 4,  5,  6,  7],
 #        [ 8,  9, 10, 11]])

Число элементов до и после изменения формы должно совпадать.

Автоматический расчёт размера

a = np.arange(12)
 matrix = a.reshape(3, -1)
 
 print(matrix.shape)
 # (3, 4)

Значение -1 разрешено только для одного измерения. NumPy вычислит нужный размер автоматически.

В NumPy 2.5 присваивание нового значения атрибуту shape объявлено устаревающим. Используйте reshape() вместо конструкции a.shape = (...).

Преобразование в одномерный массив

a = np.array([
     [1, 2],
     [3, 4]
 ])
 
 view = a.ravel()
 copy = a.flatten()
  • ravel() по возможности возвращает представление без копирования данных.
  • flatten() всегда создаёт независимую копию.

Транспонирование

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 print(a.T)
 # array([[1, 4],
 #        [2, 5],
 #        [3, 6]])

Транспонирование меняет местами оси. Для матрицы строки становятся столбцами.

Добавление измерения

a = np.array([1, 2, 3])
 
 row = a[np.newaxis, :]
 column = a[:, np.newaxis]
 
 print(row.shape)     # (1, 3)
 print(column.shape)  # (3, 1)

Альтернативная запись через None даёт тот же результат.

row = a[None, :]
 column = a[:, None]

Удаление осей длиной один

a = np.zeros((1, 3, 1))
 b = np.squeeze(a)
 
 print(b.shape)
 # (3,)

Арифметика и математические функции

Поэлементные операции

a = np.array([1, 2, 3])
 b = np.array([10, 20, 30])
 
 a + b   # array([11, 22, 33])
 a - b   # array([ -9, -18, -27])
 a * b   # array([10, 40, 90])
 b / a   # array([10., 10., 10.])
 a ** 2  # array([1, 4, 9])

Операция со скалярным значением

a = np.array([1, 2, 3])
 
 a + 10  # array([11, 12, 13])
 a * 5   # array([ 5, 10, 15])

Частые математические функции

a = np.array([1, 4, 9])
 
 np.sqrt(a)
 np.exp(a)
 np.log(a)
 np.abs(a)
 np.sin(a)
 np.cos(a)
 np.round(a, 2)
 np.floor(a)
 np.ceil(a)
 np.clip(a, 2, 7)

np.clip(a, 2, 7) заменит значения меньше 2 на 2, а значения больше 7 на 7.

Агрегирующие функции

a = np.array([10, 20, 30, 40])
 
 a.sum()          # 100
 a.mean()         # 25.0
 a.min()          # 10
 a.max()          # 40
 a.std()          # стандартное отклонение
 a.var()          # дисперсия
 np.median(a)     # 25.0
 np.percentile(a, 75)
 a.argmin()       # индекс минимального значения
 a.argmax()       # индекс максимального значения
 a.cumsum()       # накопительная сумма
 a.cumprod()      # накопительное произведение

Проверка условий

a = np.array([10, 20, 30])
 
 np.any(a > 25)   # True
 np.all(a > 0)    # True

Поэлементное и матричное умножение

a = np.array([
     [1, 2],
     [3, 4]
 ])
 
 b = np.array([
     [5, 6],
     [7, 8]
 ])
 
 elementwise = a * b
 matrix_product = a @ b

Оператор * умножает соответствующие элементы. Оператор @ выполняет матричное умножение.

elementwise
 # array([[ 5, 12],
 #        [21, 32]])
 
 matrix_product
 # array([[19, 22],
 #        [43, 50]])

Вычисления по осям

Параметр axis указывает измерение, которое функция сворачивает. Для матрицы формы (строки, столбцы) ось 0 проходит по строкам, а ось 1 проходит по столбцам.

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 a.sum(axis=0)
 # array([5, 7, 9])
 
 a.sum(axis=1)
 # array([ 6, 15])
Выражение Результат
a.sum() Сумма всех элементов
a.sum(axis=0) Сумма каждого столбца
a.sum(axis=1) Сумма каждой строки
a.mean(axis=0) Среднее каждого столбца
a.mean(axis=1) Среднее каждой строки

Сохранение числа измерений

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 mean = a.mean(axis=1, keepdims=True)
 
 print(mean)
 # array([[2.],
 #        [5.]])
 
 print(mean.shape)
 # (2, 1)

keepdims=True сохраняет свёрнутую ось длиной один. Такая форма часто упрощает последующие вычисления через broadcasting.

Broadcasting для массивов разной формы

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

Матрица и число

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 result = a * 10

Матрица и строка

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 offset = np.array([10, 20, 30])
 result = a + offset
 
 print(result)
 # array([[11, 22, 33],
 #        [14, 25, 36]])

Форма матрицы равна (2, 3), форма вектора равна (3,). Последние размеры совпадают, поэтому NumPy добавляет вектор к каждой строке.

Добавление значения к каждой строке

a = np.array([
     [1, 2, 3],
     [4, 5, 6]
 ])
 
 offset = np.array([10, 20])[:, None]
 result = a + offset
 
 print(result)
 # array([[11, 12, 13],
 #        [24, 25, 26]])

Конструкция [:, None] превращает форму (2,) в (2, 1).

Несовместимые формы

a = np.zeros((2, 3))
 b = np.zeros((2,))
 
 a + b
 # ValueError

Размеры 3 и 2 справа не совпадают, и ни один размер не равен единице.

Подробные правила приведены в разделе Broadcasting официальной документации.

Объединение и разделение массивов

concatenate

np.concatenate() соединяет массивы вдоль существующей оси.

a = np.array([[1, 2]])
 b = np.array([[3, 4]])
 
 rows = np.concatenate((a, b), axis=0)
 # array([[1, 2],
 #        [3, 4]])
 
 columns = np.concatenate((a, b), axis=1)
 # array([[1, 2, 3, 4]])

stack

np.stack() создаёт новую ось.

a = np.array([1, 2, 3])
 b = np.array([4, 5, 6])
 
 result = np.stack((a, b), axis=0)
 
 print(result)
 # array([[1, 2, 3],
 #        [4, 5, 6]])

Быстрые функции объединения

np.vstack((a, b))   # по вертикали
 np.hstack((a, b))   # по горизонтали
 np.column_stack((a, b))

Разделение массива

a = np.arange(8)
 
 parts = np.split(a, 4)
 # четыре массива по два элемента
 
 parts = np.array_split(a, 3)
 # три массива, размеры могут различаться

np.split() требует деления без остатка. np.array_split() допускает части разного размера.

Сортировка, поиск и уникальные значения

Сортировка

a = np.array([40, 10, 30, 20])
 
 sorted_a = np.sort(a)
 # array([10, 20, 30, 40])
 
 descending = np.sort(a)[::-1]
 # array([40, 30, 20, 10])

np.sort() возвращает новый массив. Метод a.sort() меняет исходный массив.

В NumPy 2.5 появился параметр descending=True.

descending = np.sort(a, descending=True)

Индексы для сортировки

a = np.array([40, 10, 30, 20])
 
 indices = np.argsort(a)
 # array([1, 3, 2, 0])
 
 sorted_a = a[indices]
 # array([10, 20, 30, 40])

Уникальные значения

a = np.array([1, 2, 2, 3, 3, 3])
 
 values = np.unique(a)
 # array([1, 2, 3])
 
 values, counts = np.unique(a, return_counts=True)
 
 print(values)  # [1 2 3]
 print(counts)  # [1 2 3]

Поиск позиции в отсортированном массиве

a = np.array([10, 20, 30, 40])
 
 position = np.searchsorted(a, 25)
 # 2

Случайные числа

Современный интерфейс NumPy использует генератор, созданный через np.random.default_rng().

rng = np.random.default_rng(42)

Случайные дробные числа

a = rng.random(5)
 matrix = rng.random((2, 3))

Случайные целые числа

a = rng.integers(0, 10, size=5)
 matrix = rng.integers(0, 100, size=(2, 3))

Верхняя граница по умолчанию не включается.

Нормальное распределение

a = rng.normal(
     loc=0,
     scale=1,
     size=1000
 )

Случайный выбор

items = np.array(["кофе", "чай", "вода"])
 
 choice = rng.choice(items)
 sample = rng.choice(items, size=2, replace=False)

Перемешивание

a = np.array([1, 2, 3, 4, 5])
 
 rng.shuffle(a)
 print(a)

shuffle() меняет исходный массив. Метод permutation() возвращает перемешанную копию.

a = np.array([1, 2, 3, 4, 5])
 shuffled = rng.permutation(a)

Одинаковый seed помогает повторить эксперимент в контролируемом окружении. Не рассчитывайте на полное совпадение последовательностей между разными генераторами и всеми будущими версиями NumPy.

Пропущенные и бесконечные значения

Значение NaN

a = np.array([10.0, np.nan, 30.0])
 
 np.isnan(a)
 # array([False,  True, False])

Проверка a == np.nan не находит пропуски. Значение NaN не равно даже самому себе. Используйте np.isnan().

Вычисления с пропусками

a = np.array([10.0, np.nan, 30.0])
 
 np.nanmean(a)   # 20.0
 np.nansum(a)    # 40.0
 np.nanmin(a)    # 10.0
 np.nanmax(a)    # 30.0
 np.nanmedian(a) # 20.0

Удаление пропусков

a = np.array([10.0, np.nan, 30.0])
 
 clean = a[~np.isnan(a)]
 # array([10., 30.])

Замена пропусков

a = np.array([10.0, np.nan, 30.0])
 
 filled = np.nan_to_num(
     a,
     nan=0.0,
     posinf=999.0,
     neginf=-999.0
 )

Проверка конечных значений

a = np.array([1.0, np.nan, np.inf, -np.inf])
 
 np.isfinite(a)
 # array([ True, False, False, False])

Целочисленный массив не может хранить np.nan. Преобразуйте данные в дробный тип.

a = np.array([1, 2, 3], dtype=np.float64)
 a[1] = np.nan

Линейная алгебра

Матричное умножение

a = np.array([
     [1, 2],
     [3, 4]
 ])
 
 b = np.array([
     [5, 6],
     [7, 8]
 ])
 
 result = a @ b

Определитель

determinant = np.linalg.det(a)

Обратная матрица

inverse = np.linalg.inv(a)

Решение системы линейных уравнений

Для системы Ax = b применяйте np.linalg.solve().

a = np.array([
     [2.0, 1.0],
     [1.0, 3.0]
 ])
 
 b = np.array([5.0, 6.0])
 
 x = np.linalg.solve(a, b)
 
 print(x)
 # array([1.8, 1.4])

Для решения системы не вычисляйте обратную матрицу вручную через np.linalg.inv(a) @ b. Функция solve() обычно точнее и эффективнее.

Норма вектора

vector = np.array([3.0, 4.0])
 
 length = np.linalg.norm(vector)
 # 5.0

Сохранение и загрузка массивов

Формат NPY

a = np.array([10, 20, 30])
 
 np.save("data.npy", a)
 
 loaded = np.load("data.npy")

Формат .npy сохраняет форму и тип массива без преобразования в текст.

Несколько массивов в одном файле

x = np.arange(5)
 y = np.arange(10, 15)
 
 np.savez_compressed(
     "arrays.npz",
     x=x,
     y=y
 )
 
 data = np.load("arrays.npz")
 
 print(data["x"])
 print(data["y"])

Текстовый файл и CSV

a = np.array([
     [1.5, 2.5],
     [3.5, 4.5]
 ])
 
 np.savetxt(
     "data.csv",
     a,
     delimiter=",",
     fmt="%.2f"
 )
 
 loaded = np.loadtxt(
     "data.csv",
     delimiter=","
 )

CSV с пропущенными значениями

loaded = np.genfromtxt(
     "data.csv",
     delimiter=",",
     skip_header=1,
     filling_values=np.nan
 )

np.loadtxt() подходит для регулярных таблиц без сложных пропусков. np.genfromtxt() обрабатывает отсутствующие значения и неоднородные строки гибче.

Не включайте allow_pickle=True при загрузке недоверенного файла. Pickle может выполнять код во время чтения данных.

Как писать быстрый код с NumPy

Заменяйте циклы операциями над массивами

Медленный вариант с циклом Python.

values = [1, 2, 3, 4]
 result = []
 
 for value in values:
     result.append(value * 2)

Вариант с NumPy.

values = np.array([1, 2, 3, 4])
 result = values * 2

Не путайте vectorize с ускорением

def calculate(x):
     return x * x + 1
 
 wrapped = np.vectorize(calculate)
 result = wrapped(np.array([1, 2, 3]))

np.vectorize() упрощает вызов обычной функции для массива, но обычно не ускоряет вычисления. Для скорости применяйте встроенные операции NumPy, ufunc-функции или специализированные библиотеки.

Не создавайте лишние копии

a = np.arange(1_000_000)
 
 view = a[100:200]
 copy = a[100:200].copy()

Представление экономит память, но остаётся связанным с исходным массивом. Копия требует дополнительную память, зато изменяется независимо.

Проверяйте тип данных

a = np.array([1, 2, 3], dtype=np.int64)
 b = a / 2
 
 print(b)
 # array([0.5, 1. , 1.5])

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

a = np.array([1, 2, 3], dtype=np.int64)
 a /= 2
 # UFuncOutputCastingError

Создайте дробный массив заранее.

a = np.array([1, 2, 3], dtype=np.float64)
 a /= 2

Частые ошибки начинающих

Проблема Причина Исправление
ModuleNotFoundError NumPy установлен в другом окружении Python Установите пакет через python -m pip install numpy и запускайте программу тем же интерпретатором
ValueError при reshape() Новая форма требует другое число элементов Сравните произведение размеров с a.size
Ошибка broadcasting Формы массивов несовместимы Выведите a.shape и b.shape, затем добавьте ось через None или измените форму
Ошибка truth value is ambiguous К массиву применили and, or или обычную проверку if array Используйте &, |, np.any() или np.all()
Исходный массив неожиданно изменился Срез вернул представление данных Создайте независимый массив через copy()
NaN не находится сравнением np.nan не равен самому себе Используйте np.isnan()
Дробная часть исчезла Данные преобразовали в целочисленный тип Примените astype(np.float64) до вычисления
IndexError Индекс вышел за границы массива Проверьте форму через a.shape и помните, что индексация начинается с нуля

Ошибка при объединении массивов

a = np.zeros((2, 3))
 b = np.zeros((3, 3))
 
 np.concatenate((a, b), axis=1)
 # ValueError

При объединении вдоль оси 1 число строк должно совпадать. Для представленных массивов подходит ось 0.

result = np.concatenate((a, b), axis=0)
 print(result.shape)
 # (5, 3)

Неодинаковая длина вложенных списков

data = [
     [1, 2, 3],
     [4, 5]
 ]
 
 a = np.array(data)
 # ValueError

Обычный числовой массив требует прямоугольной структуры. Дополните короткие строки, храните данные отдельно или выберите другую структуру данных.

Практический пример анализа продаж

В массиве каждая строка представляет магазин, а каждый столбец представляет месяц.

import numpy as np
 
 sales = np.array([
     [120, 150, 170, 160],
     [100, 130, 125, 180],
     [200, 190, 210, 230]
 ], dtype=np.float64)

Общая выручка каждого магазина

store_totals = sales.sum(axis=1)
 
 print(store_totals)
 # array([600., 535., 830.])

Общая выручка по месяцам

month_totals = sales.sum(axis=0)
 
 print(month_totals)
 # array([420., 470., 505., 570.])

Средняя выручка каждого магазина

store_means = sales.mean(axis=1)
 
 print(store_means)
 # array([150.  , 133.75, 207.5 ])

Поиск лучшего магазина

best_store = np.argmax(store_totals)
 
 print(best_store)
 # 2

NumPy возвращает индекс 2, поскольку отсчёт начинается с нуля. Лучшим стал третий магазин.

Изменение выручки между месяцами

previous = sales[:, :-1]
 current = sales[:, 1:]
 
 growth = (current - previous) / previous * 100
 
 print(np.round(growth, 1))
 # array([[ 25. ,  13.3,  -5.9],
 #        [ 30. ,  -3.8,  44. ],
 #        [ -5. ,  10.5,   9.5]])

Месяцы с выручкой выше 170

high_sales = sales > 170
 
 print(high_sales)
 # array([[False, False, False, False],
 #        [False, False, False,  True],
 #        [ True,  True,  True,  True]])

Нормализация относительно среднего магазина

mean_by_store = sales.mean(axis=1, keepdims=True)
 centered = sales - mean_by_store
 
 print(np.round(centered, 1))
 # array([[-30. ,   0. ,  20. ,  10. ],
 #        [-33.8,  -3.8,  -8.8,  46.2],
 #        [ -7.5, -17.5,   2.5,  22.5]])

Параметр keepdims=True сохраняет форму (3, 1). Broadcasting вычитает среднее каждого магазина из всех значений соответствующей строки.

Краткая шпаргалка по частым операциям

import numpy as np
 
 # Создание
 a = np.array([1, 2, 3])
 z = np.zeros((2, 3))
 o = np.ones((2, 3))
 r = np.arange(0, 10, 2)
 x = np.linspace(0, 1, 5)
 
 # Свойства
 a.shape
 a.ndim
 a.size
 a.dtype
 a.nbytes
 
 # Индексы
 a[0]
 a[-1]
 a[1:3]
 matrix[:, 0]
 matrix[0, :]
 
 # Фильтрация
 a[a > 0]
 a[(a > 0) & (a < 10)]
 np.where(a > 0, a, 0)
 
 # Форма
 a.reshape(3, 1)
 a.ravel()
 a.flatten()
 a.T
 a[:, None]
 np.squeeze(a)
 
 # Вычисления
 a.sum()
 a.mean()
 a.min()
 a.max()
 a.std()
 np.median(a)
 np.percentile(a, 90)
 np.argmax(a)
 np.any(a > 0)
 np.all(a > 0)
 
 # Объединение
 np.concatenate((a, b))
 np.stack((a, b))
 np.vstack((a, b))
 np.hstack((a, b))
 
 # Сортировка
 np.sort(a)
 np.argsort(a)
 np.unique(a, return_counts=True)
 
 # Случайные значения
 rng = np.random.default_rng(42)
 rng.random(5)
 rng.integers(0, 10, size=5)
 rng.normal(0, 1, size=100)
 rng.choice(a)
 
 # Пропуски
 np.isnan(a)
 np.isfinite(a)
 np.nanmean(a)
 np.nan_to_num(a, nan=0)
 
 # Файлы
 np.save("data.npy", a)
 a = np.load("data.npy")
 np.savetxt("data.csv", a, delimiter=",")
 a = np.loadtxt("data.csv", delimiter=",")

FAQ

Чем массив NumPy отличается от списка Python?

Массив NumPy хранит элементы одного типа в компактной области памяти и поддерживает быстрые векторные вычисления. Список Python может содержать объекты разных типов и лучше подходит для неоднородных данных.

Почему NumPy импортируют как np?

np стало общепринятым сокращением. Короткое имя делает код компактнее и сразу показывает, что функция относится к NumPy.

Что означает форма массива shape?

shape содержит размер каждой оси. Форма (2, 3) означает две строки и три столбца, а форма (5,) означает одномерный массив из пяти элементов.

Чем axis 0 отличается от axis 1?

В двумерном массиве axis=0 сворачивает строки и возвращает результат для каждого столбца. axis=1 сворачивает столбцы и возвращает результат для каждой строки.

Почему изменение среза меняет исходный массив?

Обычный срез NumPy часто возвращает представление той же памяти. Вызовите copy(), когда нужна независимая копия данных.

Когда применять arange, а когда linspace?

Применяйте arange(), когда известен шаг, особенно для целых чисел. Применяйте linspace(), когда нужно получить точное число равномерно распределённых точек.

Почему нельзя писать array == np.nan?

Значение NaN по правилам IEEE 754 не равно никакому значению, включая само себя. Проверяйте пропуски функцией np.isnan().

Ускоряет ли np.vectorize обычную функцию?

Обычно нет. np.vectorize() предоставляет удобный интерфейс, но внутри по-прежнему вызывает Python-функцию для отдельных значений. Встроенные операции NumPy работают быстрее.

Как умножить две матрицы?

Используйте оператор @ или функцию np.matmul(). Оператор * выполняет поэлементное умножение.

Как понять причину ошибки broadcasting?

Выведите формы обоих массивов через shape и сравните размеры справа налево. Каждый размер должен совпадать с парным размером или быть равным единице.

Итог

Для начала работы с NumPy достаточно уверенно освоить np.array(), свойства shape и dtype, срезы, логические маски, reshape(), параметр axis и правила broadcasting. Большая часть ошибок возникает из-за несовместимых форм, неожиданного типа данных или связи среза с исходным массивом. Проверка shape, dtype и нескольких промежуточных значений обычно быстро показывает причину проблемы.

NumPy Python массивы ndarray шпаргалка
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
17.09
11:00
Вебинар SECURITM
Как за 10 шагов превратить формальность в реальное управление рисками?
17 сентября эксперт SECURITM объяснит, где заканчивается модель угроз и начинается риск-менеджмент — и почему выбирать между ними не нужно.
Регистрируйтесь!
Реклама. 18+ ООО «Секъюритм» ИНН 7820074059

Гиганяшка

Технологии без шума вентиляторов и сухих спецификаций.

Рекламодатель
ООО «СерчИнформ»
ИНН: 7704306397
searchinform.ru↗
ИИ-ассистент СерчИнформ