В первом модуле массивы разной длины складывать было нельзя — ValueError с загадочным словом broadcast.
А массив с числом складывался всегда. На самом деле это одно и то же правило — транслирование
(broadcasting): NumPy умеет «растягивать» меньший массив до формы большего, если формы совместимы.
Строка к таблице
Цены четырёх товаров в трёх магазинах — таблица 3 × 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 мысленно повторил её три раза. Копий в памяти при этом не создаётся — «растяжение» виртуальное, поэтому это быстро.
У каждого из четырёх товаров своя скидка — множитель в discount (0.9 — скидка 10 %, 1.0 — без скидки).
Сохраните в discounted цены всех магазинов с учётом скидок.
Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
discount = np.array([0.9, 1.0, 0.8, 0.95])
discounted = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
discount = np.array([0.9, 1.0, 0.8, 0.95])
discounted = prices * discountПравила
Как NumPy решает, можно ли растянуть? Формы сравниваются справа налево, по осям:
- Если у одного массива осей меньше, слева ему дописываются оси длины 1: форма
(4,)рядом с(3, 4)считается(1, 4). - По каждой оси размеры должны совпадать или один из них должен быть равен 1 — такая ось растягивается.
- Иначе — ошибка.
| Формы | Результат | Почему |
|---|---|---|
(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)?
(4,) дополняется слева единицей до (1, 4); 1 растягивается до 3, 4 совпадает с 4. Результат — (3, 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. ]]
Сохраните в dev таблицу отклонений баллов каждого студента от среднего по предмету (форма 30 × 5), а в
above — сколько всего оценок в таблице выше среднего по своему предмету.
scores - scores.mean(axis=0) — таблица минус строка средних.dev > 0 и её сумма.Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
dev = ...
above = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
dev = scores - scores.mean(axis=0)
above = (dev > 0).sum()Когда формы не подходят
store_markup = np.array([1.1, 1.2, 1.05])
prices * store_markupValueError: 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,)
В weeks — максимальные температуры, разложенные по неделям (52 × 7). Сохраните в vs_weekday, насколько
каждый день теплее или холоднее среднего своего дня недели за год.
weeks.mean(axis=0), форма (7,).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
vs_weekday = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
vs_weekday = weeks - weeks.mean(axis=0)Итоги
- Транслирование растягивает меньший массив до формы большего без копирования.
- Формы сравниваются справа налево; по каждой оси — равны или одна из них 1.
- Одномерный массив прикладывается к таблице как строка.
- Таблица минус
mean(axis=0)— отклонения от средних по столбцам.