Нашли ошибку?
Скачать чистый
урок 1 из 4≈ 15 минупражнения: 0 из 3

Массивы разной формы

Как NumPy складывает таблицу со строкой — правила транслирования (broadcasting) и как по формам заранее понять, получится ли операция.

Python запустится при первом выполнении

В первом модуле массивы разной длины складывать было нельзя — ValueError с загадочным словом broadcast. А массив с числом складывался всегда. На самом деле это одно и то же правило — транслирование (broadcasting): NumPy умеет «растягивать» меньший массив до формы большего, если формы совместимы.

Строка к таблице

Цены четырёх товаров в трёх магазинах — таблица 3 × 4. Доставка у каждого товара своя, одна на все магазины — это одна строка из четырёх чисел. Прибавим строку к таблице:

[ ]Таблица 3 × 4 плюс строка из 4
import numpy as np

prices = np.array([
    [120, 80, 45, 300],   # магазин 1: четыре товара
    [130, 85, 50, 290],   # магазин 2
    [110, 90, 40, 310],   # магазин 3
])
delivery = np.array([20, 10, 5, 40])   # доставка каждого товара
print(prices.shape, delivery.shape)
prices + delivery
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(3, 4) (4,)
array([[140,  90,  50, 340],
       [150,  95,  55, 330],
       [130, 100,  45, 350]])

Строка прибавилась к каждой строке таблицы: NumPy мысленно повторил её три раза. Копий в памяти при этом не создаётся — «растяжение» виртуальное, поэтому это быстро.

[ ]Упражнение 1Скидки по товарам решено

У каждого из четырёх товаров своя скидка — множитель в discount (0.9 — скидка 10 %, 1.0 — без скидки). Сохраните в discounted цены всех магазинов с учётом скидок.

discount = np.array([0.9, 1.0, 0.8, 0.95])
discounted = ...

Правила

Как NumPy решает, можно ли растянуть? Формы сравниваются справа налево, по осям:

  1. Если у одного массива осей меньше, слева ему дописываются оси длины 1: форма (4,) рядом с (3, 4) считается (1, 4).
  2. По каждой оси размеры должны совпадать или один из них должен быть равен 1 — такая ось растягивается.
  3. Иначе — ошибка.
Формы Результат Почему
(3, 4) и число (3, 4) число растягивается на всё
(3, 4) и (4,) (3, 4) (4,) → (1, 4), строка повторяется 3 раза
(3, 4) и (3,) ошибка справа 4 и 3 — не равны и не 1
(5,) и (4,) ошибка 5 и 4 — не равны и не 1

Последняя строка таблицы — наша ошибка из первого модуля: массивы разной длины.

Вопрос

Какая форма получится у np.zeros((3, 4)) + np.zeros(4)?

Отклонение от среднего по столбцу

Самое частое применение: вычесть из таблицы итог по столбцам. scores.mean(axis=0) — средние по пяти предметам, форма (5,) — как раз строка. Вычитаем её из таблицы 30 × 5 — и получаем, насколько каждый студент выше или ниже среднего по каждому предмету:

[ ]Отклонение от среднего по предмету
scores = np.loadtxt("data/scores.csv", delimiter=",", skiprows=1, usecols=(1, 2, 3, 4, 5))
subject_mean = scores.mean(axis=0)
print(subject_mean.shape)
print(np.round(scores[:3] - subject_mean, 1))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(5,)
[[  0.2 -17.8  -1.   12.3  15. ]
 [  2.2  -0.8  -1.    7.3  21. ]
 [ -6.8  -8.8   3.   -9.7   4. ]]
[ ]Упражнение 2Выше или ниже среднего решено

Сохраните в dev таблицу отклонений баллов каждого студента от среднего по предмету (форма 30 × 5), а в above — сколько всего оценок в таблице выше среднего по своему предмету.

dev = ...
above = ...

Когда формы не подходят

[ ]Таблица 3 × 4 и массив из 3ошибка: ValueError
store_markup = np.array([1.1, 1.2, 1.05])
prices * store_markup
Ошибкасохранённый · нажмите «Выполнить», чтобы получить свой
ValueError: operands could not be broadcast together with shapes (3,4) (3,) 

Ещё один пример — погода. Разложим год по неделям, как в модуле 3:

[ ]Температуры по неделям
tmax = np.loadtxt("data/moscow_2025.csv", delimiter=",", skiprows=1, usecols=2)
weeks = tmax[:364].reshape(52, 7)
print(weeks.shape, weeks.mean(axis=0).shape)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(52, 7) (7,)
[ ]Упражнение 3Отклонение от среднего дня недели решено

В weeks — максимальные температуры, разложенные по неделям (52 × 7). Сохраните в vs_weekday, насколько каждый день теплее или холоднее среднего своего дня недели за год.

vs_weekday = ...

Итоги

  • Транслирование растягивает меньший массив до формы большего без копирования.
  • Формы сравниваются справа налево; по каждой оси — равны или одна из них 1.
  • Одномерный массив прикладывается к таблице как строка.
  • Таблица минус mean(axis=0) — отклонения от средних по столбцам.

Подробнее в справочнике

Нашли ошибку?