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

Склеить и разделить

Собрать массив из частей — np.concatenate по существующей оси, np.stack с новой осью, np.vstack и np.hstack — и разрезать его на части np.split.

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

Данные часто приходят по частям: продажи за январь и за февраль в разных файлах, каждая метеостанция в своём. Чтобы считать по ним вместе, части нужно склеить в один массив. Бывает и наоборот: месяц нужно разрезать на недели.

Продолжить массив: np.concatenate

np.concatenate([a, b, …]) ставит массивы друг за другом. Массивы передают списком — в квадратных скобках:

[ ]Два массива в один
import numpy as np

a = np.array([1, 2, 3])
b = np.array([10, 20])
print(np.concatenate([a, b]))
print(np.concatenate([b, a, b]))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[ 1  2  3 10 20]
[10 20  1  2  3 10 20]
[ ]Упражнение 1Январь и февраль решено

В jan и feb — выручка кофейни за первые дни января и февраля. Сохраните в all_sales один массив: сначала январские дни, потом февральские, — а в total сумму выручки за все эти дни.

jan = np.array([410, 385, 402, 395, 430])
feb = np.array([398, 441, 420, 415])
all_sales = ...
total = ...

У двумерных массивов concatenate склеивает по оси axis= — как агрегаты: axis=0 (по умолчанию) ставит таблицы друг под другом, добавляя строки, axis=1 — рядом, добавляя столбцы. Размер по другой оси должен совпадать:

[ ]Две таблицы: под и рядом
t1 = np.array([[1, 2], [3, 4]])
t2 = np.array([[5, 6], [7, 8]])
print(np.concatenate([t1, t2]))            # axis=0: строки добавились
print(np.concatenate([t1, t2], axis=1))    # axis=1: столбцы добавились
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
[[1 2 5 6]
 [3 4 7 8]]

Новая ось: np.stack

Три метеостанции записали по 28 дней — три одномерных массива формы (28,). Хочется таблицу 3 × 28: строка — станция. concatenate тут не поможет: он продолжит массив до 84 чисел. Нужна новая ось — её добавляет np.stack:

[ ]concatenate и stack
center = np.genfromtxt("data/station_center.csv", delimiter=",", skip_header=1)
airport = np.genfromtxt("data/station_airport.csv", delimiter=",", skip_header=1)
forest = np.genfromtxt("data/station_forest.csv", delimiter=",", skip_header=1)
temps_long = np.concatenate([center[:, 1], airport[:, 1], forest[:, 1]])
temps = np.stack([center[:, 1], airport[:, 1], forest[:, 1]])
print(temps_long.shape)
print(temps.shape)
print(temps[:, :4])     # три станции, первые четыре дня
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
(84,)
(3, 28)
[[-5.3 -5.3 -5.7 -5.7]
 [-6.4 -6.5 -6.3 -8.1]
 [-6.7 -8.7 -9.2 -9.1]]

np.stack кладёт массивы одинаковой формы друг на друга: из нескольких (n,) получается (k, n), где k — сколько массивов. С axis=1 новой осью станут столбцы: (n, k).

Вопрос

x и y — массивы формы (5,). Какая форма у np.stack([x, y])?

[ ]Упражнение 2Влажность трёх станций решено

Загружены все три станции: center, airport, forest. Соберите в hum таблицу влажности (столбец 2 каждого файла): строка — станция в этом порядке, столбец — день. В hum_avg сохраните среднюю влажность каждой станции без учёта пропусков.

hum = ...
hum_avg = ...

Короче: np.vstack и np.hstack

Для двух частых случаев есть короткие имена. np.vstack (vertical — вертикально) ставит массивы друг под другом, np.hstack (horizontal — горизонтально) — рядом. Для таблиц это concatenate с axis=0 и axis=1, а одномерные массивы vstack делает строками — как stack:

[ ]vstack и hstack
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
print(np.vstack([x, y]))
print(np.hstack([x, y]))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[[1 2 3]
 [4 5 6]]
[1 2 3 4 5 6]

Склеивать можно только подходящие куски: у vstack должна совпадать длина строк, у hstack — число строк.

[ ]Строки разной длиныошибка: ValueError
np.vstack([np.array([1, 2, 3]), np.array([4, 5])])
Ошибкасохранённый · нажмите «Выполнить», чтобы получить свой
ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 2

Частый случай — добавить к таблице столбец. Одномерный массив hstack к таблице не приклеит: у них разное число осей. Сначала превратите его в столбец (n, 1) — через np.newaxis из модуля о транслировании:

[ ]Приклеить столбец
scores = np.array([[70, 80], [65, 90], [88, 72]])
bonus = np.array([5, 0, 3])
print(np.hstack([scores, bonus[:, np.newaxis]]))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[[70 80  5]
 [65 90  0]
 [88 72  3]]
[ ]Упражнение 3Столбец с суммой решено

В order — строки заказа: цена товара и количество. Сохраните в table ту же таблицу с третьим столбцом — суммой по строке (цена × количество).

order = np.array([[120, 3], [80, 5], [200, 1], [45, 12]])
table = ...

Разрезать: np.split

np.split(a, n) режет массив на n равных частей и возвращает список массивов. Части можно сразу разложить по переменным. Вместо числа частей можно передать список мест разреза — номера, с которых начинается следующая часть:

[ ]Равные части и места разреза
days = np.arange(1, 15)
first, second = np.split(days, 2)
print(first)
print(second)
print(np.split(days, [3, 10]))    # новые части начинаются с индексов 3 и 10
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[1 2 3 4 5 6 7]
[ 8  9 10 11 12 13 14]
[array([1, 2, 3]), array([ 4,  5,  6,  7,  8,  9, 10]), array([11, 12, 13, 14])]

Список массивов Python печатает как [array([...]), array([...])] — array здесь просто подпись: каждый элемент списка — массив NumPy.

Если массив не делится на равные части, split не угадывает, куда деть остаток, а сообщает об ошибке:

[ ]14 на 3 не делитсяошибка: ValueError
np.split(days, 3)
Ошибкасохранённый · нажмите «Выполнить», чтобы получить свой
ValueError: array split does not result in an equal division

Список частей одной длины можно снова собрать np.stack — получится таблица, где строка — часть:

[ ]Упражнение 4Февраль по неделям решено

В center_temp — температура в центре за 28 дней февраля. Разрежьте её на четыре недели и соберите в weeks таблицу 4 × 7: строка — неделя. В week_avg сохраните среднюю температуру каждой недели без учёта пропусков.

center_temp = center[:, 1]
weeks = ...
week_avg = ...

Ту же таблицу даёт center_temp.reshape(4, 7) из модуля об индексах. split удобнее, когда части разной длины (np.split(a, [7, 14])) или нужны отдельными переменными.

Итоги

  • np.concatenate([a, b], axis=…) продолжает массив по существующей оси.
  • np.stack([a, b]) добавляет новую ось: из k массивов (n,) — таблица (k, n).
  • np.vstack — друг под другом, np.hstack — рядом; размеры по другой оси должны совпадать.
  • Столбец к таблице — np.hstack([table, col[:, np.newaxis]]).
  • np.split(a, n) — n равных частей, np.split(a, [i, j]) — разрез по местам; результат — список.

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

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