Объединение данных в единую структуру — это операция, с которой сталкиваются при поступлении данных. С помощью нее мы можем объединять данные из разных источников, а также асинхронные ответы сервера и результаты параллельных и последовательных вычислений. В стандартном Python есть структуры данных list
и set
. Их можно объединять с помощью append()
и update()
. Еще можно использовать функцию zip()
— она нужна для попарного объединения значений. В Numpy это работает по-другому.
Массивы numpy.ndarray
поддерживают сценарии объединения массивов различной размерности по разным осям индексов. Для этого используются четыре метода:
- Конкатенация —
concatenate()
- Объединение массивов по горизонтали —
hstack()
- Объединение массивов по вертикали —
vstack()
- Попарное объединение элементов списков —
column_stack()
В этом уроке мы рассмотрим правила их применения и узнаем, какие нюансы нужно учитывать в работе с ними.
Одномерные структуры данных
Начнем с одномерных структур данных, потому что они встречаются чаще всего.
Объединение списков значений в Python делаются операцией +
. В Numpy ту же роль выполняют методы concatenate()
и hstack()
:
import numpy as np
arr1 = np.array([0, 1, 2, 3,])
arr2 = np.array([4, 5, 6, 7])
print(np.concatenate([arr1, arr2]))
# => [0 1 2 3 4 5 6 7]
print(np.hstack([arr1, arr2]))
# => [0 1 2 3 4 5 6 7]
print([0, 1, 2, 3,] + [4, 5, 6, 7])
# => [0, 1, 2, 3, 4, 5, 6, 7]
Обратите внимание, что в примере выше мы объединили массивы по горизонтали. Для этого мы использовали метод hstack()
(сокращение от английского horisontal stack).
А теперь попробуем объединить массивы в вертикальном направлении. Здесь понадобится метод vstack()
(от англ. vertical stack). Для вертикального объединения также подойдет инициализация нового массива из списка исходных массивов. Этот подход аналогичен формированию списка списков:
print(np.vstack([arr1, arr2]))
# => [[0 1 2 3]
# [4 5 6 7]]
print(np.array([arr1, arr2]))
# => [[0 1 2 3]
# [4 5 6 7]]
print([[0, 1, 2, 3,], [4, 5, 6, 7]])
# => [[0, 1, 2, 3], [4, 5, 6, 7]]
Еще одна удобная и распространенная операция — попарное объединение элементов списков. Как уже говорили, в стандартном Python для этой цели используется метод zip()
.
В Numpy используется аналог — метод column_stack()
:
print(list(zip([0, 1, 2, 3,], [4, 5, 6, 7])))
# => [(0, 4), (1, 5), (2, 6), (3, 7)]
print(np.column_stack([arr1, arr2]))
# => [[0 4]
# [1 5]
# [2 6]
# [3 7]]
В итоге мы рассмотрели все четыре метода и выяснили, как они работают для одномерных массивов. Эти же знания применимы и к массивам с большей размерностью.
Двумерные структуры данных
Попробуем объединить двумерные структуры — матрицы. Это можно сделать в двух направлениях.
В этом примере мы объединим данные по вертикали:
arr1 = np.array([[5, 8], [8, 9]])
arr2 = np.array([[3, 1], [7, 2]])
print(np.concatenate([arr1, arr2]))
# => [[5 8]
# [8 9]
# [3 1]
# [7 2]]
print(np.vstack([arr1, arr2]))
# => [[5 8]
# [8 9]
# [3 1]
# [7 2]]
Также можно объединять данные по горизонтали:
print(np.concatenate([arr1, arr2], axis = 1))
# => [[5 8 3 1]
# [8 9 7 2]]
print(np.hstack((arr1, arr2)))
# => [[5 8 3 1]
# [8 9 7 2]]
Все примеры выше демонстрировали объединение двух массивов. Однако массивов может быть больше.
Многомерные структуры данных
Предположим, что в результате асинхронных запросов к серверу было получено три списка значений для трех дней продаж магазина. Чтобы объединить ответы сервера в единую таблицу, можно использовать все те же методы:
response_values_day1 = np.array([7, 1, 7, 8])
response_values_day2 = np.array([4, 2, 4, 5])
response_values_day3 = np.array([3, 5, 2, 3])
orders = np.vstack([
response_values_day1,
response_values_day2,
response_values_day3,
])
print(orders)
# => [[7 1 7 8]
# [4 2 4 5]
# [3 5 2 3]]
Запросы к серверу могут быть не по дням, а по магазинам. В этом случае также применимы методы объединения:
response_values_shop1 = np.array([ 7, 4, 3,])
response_values_shop2 = np.array([ 1, 2, 5,])
response_values_shop3 = np.array([ 7, 4, 2,])
response_values_shop4 = np.array([ 8, 5, 3,])
orders = np.vstack([
response_values_shop1,
response_values_shop2,
response_values_shop3,
response_values_shop4,
])
print(orders.T)
# => [[7 1 7 8]
# [4 2 4 5]
# [3 5 2 3]]
В примере выше используется транспонирование матрицы. Результат транспонирования — это матрица, в которой столбцы исходной таблицы становятся строками.
Посмотрим на исходную матрицу:
print(orders)
# => [[7 4 3]
# [1 2 5]
# [7 4 2]
# [8 5 3]]
А теперь сравним ее с транспонированной:
print(orders.T)
# => [[7 1 7 8]
# [4 2 4 5]
# [3 5 2 3]]
Выводы
В этом уроке мы рассмотрели методы объединения массивов numpy.ndarray
. Все методы работают для данных с разной размерностью: одномерными, двумерными и многомерными. При этом на вход методы могут получать любое количество массивов.
Чтобы выбрать правильный метод объединения, проговорите про себя, что нужно сделать:
- Если горизонтально состыковать массивы, используем
hstack()
- Если вертикально состыковать массивы, используем
vstack()
- Если объединить значений поэлементно из нескольких колонок, используем
column_stack()
Самостоятельная работа
Нажмите, чтобы увидеть тестовые данные
word_array = ['мыла', 'мама', 'мама', 'раму', 'мыла', 'мама']
Современные переводчики и анализаторы текста используют алгоритмы на основе глубоких нейронных сетей. Данные алгоритмы оперируют числовыми представлениями слов разной размерности:
-
Полносвязные нейронные сети используют векторы
-
Рекуррентные и сверточные нейронные сети делают преобразование над матрицами
Попробуем подготовить текстовые данные для обоих подходов глубокого обучения:
Шаг 1. Поработаем с одномерными представлениями. Вспомним кодировку текста в числовые данные:
мама = (0,2,1)
мыла = (1,3,0)
раму = (1,1,2)
мама мыла раму =['мама','мыла','раму'] = [0,2,1,1,3,0,1,1,2]
Напишите функцию word2vec()
, которая получает на вход список слов и кодирует их в список чисел. Постарайтесь использовать методы объединения массивов numpy.ndarray
.
Нажмите, чтобы увидеть ответ
def test(code_array: np.array):
expected_code_array = np.array([1, 3, 0, 0, 2, 1, 0, 2, 1, 1, 1, 2, 1, 3, 0, 0, 2, 1])
# shape
assert code_array.shape == expected_code_array.shape
# type
assert np.array_equal(code_array, expected_code_array)
def word2vec(word_array):
code_rules = {
'мама' : (0,2,1),
'мыла' : (1,3,0),
'раму' : (1,1,2)
}
return np.hstack([np.array(code_rules[one_word]) for one_word in word_array])
code_array = word2vec(word_array)
test(code_array)
Шаг 2. Сделаем преобразование для двумерных представлений:
мама = (0,2,1)
мыла = (1,3,0)
раму = (1,1,2)
мама мыла раму = ['мама', 'мыла', 'раму'] = [[0,2,1],[1,3,0],[1,1,2]]
Это и есть матричное представление текста, в котором векторные представления слов расположены по строкам по порядку сверху вниз. Напишите функцию word2matrix()
, которая получает на вход список слов и кодирует их в матричное представление (массив numpy.ndarray
). Постарайтесь использовать методы объединения массивов numpy.ndarray
.
Нажмите, чтобы увидеть ответ
def test(code_array: np.array):
expected_code_array = np.array([
[1, 3, 0],
[0, 2, 1],
[0, 2, 1],
[1, 1, 2],
[1, 3, 0],
[0, 2, 1]]
)
# shape
assert code_array.shape == expected_code_array.shape
# type
assert np.array_equal(code_array, expected_code_array)
def word2matrix(word_array):
code_rules = {
'мама' : (0,2,1),
'мыла' : (1,3,0),
'раму' : (1,1,2)
}
return np.vstack([np.array(code_rules[one_word]) for one_word in word_array])
code_array = word2matrix(word_array)
test(code_array)
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.