Урок курса
Объединение массивов: concatenate и stack
NumPy и pandas: практический тренажёрЧем stack отличается от concatenate
np.concatenate соединяет массивы вдоль существующей оси. np.stack создаёт новую ось; входные массивы должны иметь одинаковую форму. Вот результат для двух векторов длины 2:
import numpy as np
a = np.array([1, 2])
b = np.array([3, 4])
print(np.concatenate([a, b]).tolist())
print(np.stack([a, b], axis=0).tolist())
print(np.stack([a, b], axis=1).tolist())Результат:
[1, 2, 3, 4]
[[1, 2], [3, 4]]
[[1, 3], [2, 4]]Формы результатов: (4,), (2, 2), (2, 2). При concatenate размеры должны совпадать по всем осям, кроме оси соединения. У одномерного массива есть только ось 0: для столбцов сначала создайте вторую ось либо используйте stack.
В предыдущих уроках мы работали с отдельными массивами: считали агрегаты, обнаруживали NaN, управляли формой. Теперь встаёт другой вопрос — как склеить несколько массивов в один. Именно здесь начинается работа с np.concatenate и np.stack.
np.concatenate: объединение по существующей оси
Когда нужно склеить несколько массивов в один, первый инструмент — np.concatenate. Его сигнатура выглядит так:
np.concatenate([arr1, arr2, ...], axis=k)
Параметр axis=k указывает, вдоль какой из уже существующих осей происходит «склейка». Ключевое слово здесь — существующей: concatenate не добавляет новых измерений, он только удлиняет массив по одной из тех осей, которые уже есть.
Чтобы операция прошла без ошибки, входные массивы должны удовлетворять двум условиям:
- одинаковое число осей (одинаковый
ndim); - совпадающие размеры по всем осям, кроме той, вдоль которой идёт склейка.
Правило для shape результата простое. Пусть все входные массивы имеют ndim=2, и мы склеиваем по оси 0. Тогда по оси 0 берём сумму размеров всех входных массивов; по оси 1 — размер остаётся тем же, что у каждого входного (они обязаны совпадать).
В общем виде: если склеиваем по оси k, то размер результата по оси k равен сумме соответствующих размеров входных массивов, а по всем остальным осям размер совпадает с размером входных.
Конкретно: два массива shape (2, 3) при axis=0 дают (4, 3), при axis=1 дают (2, 6). Это можно проверить ещё до запуска кода — сложить нужные цифры вручную.
Нарушение условий совместимости NumPy сразу сообщит ошибкой ValueError: all the input array dimensions except for the concatenation axis must match exactly. Это сигнал: посмотри на shape всех входных массивов и найди несовпадение.
Практика np.concatenate по осям 0 и 1
Посмотрим, как работает concatenate на конкретном коде. Возьмём два двумерных массива одинаковой формы:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
b = np.array([[7, 8, 9], [10, 11, 12]]) # shape (2, 3)
# Склеиваем по оси 0 — добавляем строки
r0 = np.concatenate([a, b], axis=0)
print(r0.shape) # (4, 3)
print(r0)
# [[ 1 2 3]
# [ 4 5 6]
# [ 7 8 9]
# [10 11 12]]
# Склеиваем по оси 1 — добавляем столбцы
r1 = np.concatenate([a, b], axis=1)
print(r1.shape) # (2, 6)
print(r1)
# [[ 1 2 3 7 8 9]
# [ 4 5 6 10 11 12]]
При axis=0 массивы встают друг под другом: строк стало 2+2=4, а три столбца остались. При axis=1 — встают рядом: строки те же две, а столбцов стало 3+3=6.
Одномерный случай немного отличается — у вектора только одна ось, поэтому axis=0 единственный вариант:
x = np.array([1, 2, 3]) # shape (3,)
y = np.array([4, 5]) # shape (2,)
result = np.concatenate([x, y], axis=0)
print(result.shape) # (5,)
print(result) # [1 2 3 4 5]
Обратите внимание: здесь x и y имеют разные длины, и это нормально — по единственной оси размеры суммируются, никаких дополнительных ограничений нет.
Главное, что стоит закрепить из этих примеров: shape результата всегда можно посчитать вручную ещё до запуска. Берёте shape входных массивов, в позиции оси k складываете числа, по остальным позициям оставляете как есть. Если цифры не сходятся — NumPy выдаст ValueError ещё до того, как что-то пойдёт не так в логике программы.
np.stack: создание новой оси и практика по разным позициям
np.stack решает другую задачу: он не удлиняет массив вдоль существующей оси, а создаёт новую ось и складывает массивы вдоль неё. Это единственное, но принципиальное отличие от concatenate.
Сигнатура:
np.stack([arr1, arr2, ...], axis=k)
Параметр axis=k теперь означает: на какую позицию в кортеже shape вставить новое измерение. После вставки размер по этой позиции будет равен числу сложенных массивов.
Жёсткое требование: все входные массивы должны иметь строго одинаковую shape. Не просто совпадать по одной оси — а быть идентичными по всем осям. Если хотя бы один массив отличается, NumPy выбросит ValueError.
Одномерный случай
Возьмём два вектора shape (3,):
import numpy as np
a = np.array([1, 2, 3]) # shape (3,)
b = np.array([4, 5, 6]) # shape (3,)
# Новая ось в позиции 0 — массивы становятся строками
s0 = np.stack([a, b], axis=0)
print(s0.shape) # (2, 3)
print(s0)
# [[1, 2, 3],
# [4, 5, 6]]
# Новая ось в позиции 1 — массивы становятся столбцами
s1 = np.stack([a, b], axis=1)
print(s1.shape) # (3, 2)
print(s1)
# [[1, 4],
# [2, 5],
# [3, 6]]
При axis=0 два вектора длиной 3 превращаются в матрицу (2, 3): два — это число массивов, 3 — исходная длина. При axis=1 новая ось вставляется между существующей длиной и ничем: получаем (3, 2). Можно представить это как «каждый элемент вектора теперь имеет два значения — из a и из b».
Двумерный случай
Когда входные массивы двумерные, результат np.stack будет трёхмерным — новое измерение добавляется к уже существующим двум:
A = np.ones((3, 4)) # shape (3, 4)
B = np.ones((3, 4)) * 2 # shape (3, 4)
print(np.stack([A, B], axis=0).shape) # (2, 3, 4)
print(np.stack([A, B], axis=1).shape) # (3, 2, 4)
print(np.stack([A, B], axis=2).shape) # (3, 4, 2)
Логика прямая: берёте исходный кортеж (3, 4) и вставляете 2 (число массивов) на позицию axis:
axis=0→ вставляем2перед3, 4→(2, 3, 4)axis=1→ вставляем2между3и4→(3, 2, 4)axis=2→ вставляем2после3, 4→(3, 4, 2)
Эта операция вставки — ключ к тому, как читать shape результата np.stack без запуска кода. Нужно знать: сколько массивов складываете и куда вставляете новое измерение.
Разница между concatenate и stack: алгоритм проверки shape
Оба инструмента объединяют массивы, но делают это принципиально по-разному. np.concatenate работает с уже существующими осями: число измерений результата совпадает с числом измерений входных массивов, а один из размеров увеличивается. np.stack создаёт новую ось: результат всегда имеет на одно измерение больше, чем входные.
Это различие хорошо видно на одномерных векторах:
np.concatenate([a, b], axis=0)для двух векторов shape(n,)даёт shape(2n,)— один длинный вектор.np.stack([a, b], axis=0)для тех же векторов даёт shape(2, n)— матрицу из двух строк.
Результаты морфологически разные, хотя данные «те же самые».
Алгоритм предсказания shape для concatenate
Чтобы узнать shape результата до запуска кода, достаточно трёх шагов:
- Выпишите shape каждого входного массива.
- Убедитесь, что по всем осям, кроме
k, размеры совпадают — иначе будетValueError. - По оси
kсложите соответствующие размеры всех входных массивов; по остальным осям оставьте размер как есть.
Пример: массивы (2, 3) и (2, 3) при axis=0 → складываем первые числа: 2+2=4, второе остаётся 3 → результат (4, 3).
Алгоритм предсказания shape для stack
- Убедитесь, что все входные массивы имеют строго одинаковую shape.
- Возьмите исходный кортеж shape.
- Вставьте число массивов
nв позициюkэтого кортежа.
Пример: два массива (3, 4) при axis=1 → берём (3, 4), вставляем 2 на позицию 1 → (3, 2, 4).
Этот алгоритм работает для любого числа осей и любого числа складываемых массивов. Если складываете пять массивов shape (6, 7) через np.stack(axis=0), результат — (5, 6, 7): число массивов на нулевую позицию, исходная форма следом.
Главный практический вопрос при выборе между двумя функциями: нужно ли сохранить число осей или добавить новое измерение? Если нужно просто удлинить — concatenate. Если нужно «сложить в стопку» с сохранением структуры каждого массива — stack.
Закрепите тему на задачах
Сначала решите, нужна ли новая ось. concatenate объединяет вдоль существующей, stack создаёт новую. Выпишите итоговую shape до запуска.
NumPy stack: axis=0, 1 и 2 и форма результата
NumPy concatenate и stack: сравните ndim и shape
Откройте условие и решите задачу перед чтением следующей темы. В задачах на код проверяется программа, в тестовых заданиях — выбранный ответ. Для последовательного обучения вернитесь в программу бесплатного курса.
Задача 1
Даны два массива shape (3, 4). Какой shape будет у результата np.concatenate([a, b], axis=1)?
Задача 2
Даны два массива shape (5,). Что вернёт np.stack([a, b], axis=0)?
Задача 3
Даны массивы a и b одинаковой формы (2, 3). Какое выражение объединит их по оси 0 и добавит строки?
Задача 4
np.concatenate по двум осям: предсказание и проверка shape
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая:
- Читает из
stdinчетыре целых числа в одной строке:R,C,R2,C2. - Создаёт два двумерных массива:
a = np.arange(R * C).reshape(R, C)— shape(R, C);b = np.arange(R2 * C2).reshape(R2, C2)— shape(R2, C2).
- Если
C == C2— выполняетr0 = np.concatenate([a, b], axis=0)и выводит shaper0в одну строку. - Если
R == R2— выполняетr1 = np.concatenate([a, b], axis=1)и выводит shaper1в следующую строку. - Гарантируется, что выполнимо хотя бы одно условие; оба могут быть выполнимы одновременно — тогда выводятся обе строки в указанном порядке.
Каждую строку выводите в виде Python-кортежа, например (4, 3).
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
Одна строка: четыре целых числа R C R2 C2, разделённых пробелами.
Формат вывода
Одна или две строки. Если C == C2 — первой строкой shape результата np.concatenate([a, b], axis=0). Если R == R2 — следующей строкой shape результата np.concatenate([a, b], axis=1). Каждый shape — в виде Python-кортежа.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 5
np.stack по трём позициям оси: предсказание и проверка shape
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая:
- Читает из
stdinтри целых числа в одной строке:R,C,n— число строк, столбцов и количество одинаковых двумерных массивов. - Создаёт
nдвумерных массивов одинаковой формы(R, C), гдеi-й массив равенnp.arange(i * R * C, (i + 1) * R * C).reshape(R, C)дляiот0доn-1. - Складывает все
nмассивов черезnp.stackсaxis=0, затем сaxis=1, затем сaxis=2. Сохраняет результаты в переменныеs0,s1,s2. - Выводит в
stdoutтри строки — shape каждого результата в виде Python-кортежа:
- строка 1: shape
s0; - строка 2: shape
s1; - строка 3: shape
s2.
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
Одна строка: три целых числа R C n, разделённых пробелами. Гарантируется R >= 2, C >= 2, n >= 2.
Формат вывода
Три строки. Каждая — shape соответствующего результата np.stack в виде Python-кортежа, например (3, 2, 4).
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 6
concatenate vs stack на одномерных векторах: разница в ndim и shape
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая наглядно показывает разницу между np.concatenate и np.stack на одномерных массивах:
- Читает из
stdinодну строку с двумя целыми числами:nиk— длина каждого изkодномерных векторов. - Создаёт
kодномерных массивов:i-й массив (iот0доk-1) равенnp.arange(i * n, (i + 1) * n)— shape(n,). - Объединяет все
kмассивов черезnp.concatenate(..., axis=0)→cat. Выводит строку:cat shape=<shape> ndim=<ndim>. - Складывает все
kмассивов черезnp.stack(..., axis=0)→st0. Выводит строку:st0 shape=<shape> ndim=<ndim>. - Складывает все
kмассивов черезnp.stack(..., axis=1)→st1. Выводит строку:st1 shape=<shape> ndim=<ndim>. - Выводит строку
ndim_diff=<d>, где<d>— разницаst0.ndim - cat.ndim.
Shape выводите в виде Python-кортежа, например (6,) или (2, 3).
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
Одна строка: два целых числа n k, разделённых пробелом. Гарантируется n >= 2, k >= 2.
Формат вывода
Четыре строки:
cat shape=<shape> ndim=<ndim>
st0 shape=<shape> ndim=<ndim>
st1 shape=<shape> ndim=<ndim>
ndim_diff=<d>
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 7
Найди и исправь: неверные axis в concatenate и stack
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет.
В редакторе уже есть сломанный код. Он пытается выполнить четыре операции объединения массивов, но в каждой из четырёх допущена ошибка: либо перепутан axis в np.concatenate, либо неверна позиция новой оси в np.stack, либо массивы переданы в неправильном порядке.
Что нужно сделать
Найдите и исправьте все четыре ошибки так, чтобы программа:
- Читала из
stdinчетыре целых числа в одной строке:R,C,R2,n. - Создавала:
a = np.arange(R * C).reshape(R, C)— shape(R, C);b = np.arange(R2 * C).reshape(R2, C)— shape(R2, C);- список из
nодномерных массивовvecs, гдеi-й равенnp.arange(i * C, (i + 1) * C)— shape(C,)каждый.
- Выполняла четыре операции и выводила shape каждого результата в отдельной строке:
op1 = np.concatenate([a, b], axis=0)— склейка по строкам; shape(R + R2, C);op2 = np.concatenate([a, a], axis=1)— склейка по столбцам; shape(R, 2 * C);op3 = np.stack(vecs, axis=0)— новая ось в позиции 0; shape(n, C);op4 = np.stack(vecs, axis=1)— новая ось в позиции 1; shape(C, n).
Каждый shape выводите в виде Python-кортежа, например (4, 3).
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
Одна строка: четыре целых числа R C R2 n, разделённых пробелами. Гарантируется R >= 2, C >= 2, R2 >= 1, n >= 2.
Формат вывода
Четыре строки — shape каждой операции в виде Python-кортежа.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задачи к уроку
- NumPy stack: axis=0, 1 и 2 и форма результата
Соедините массивы через np.stack по разным осям и предскажите shape результата. Практика NumPy онлайн.
- NumPy concatenate и stack: чем отличаются shape и axis
concatenate объединяет по существующей оси, stack добавляет новую. Сравните формы результатов NumPy и решите задачу в браузере.
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
