Open in Colab

© Семён Лукашевский сайт автора

Индексация, срезы, итерирование

Одномерные массивы очень похожи на простые списки Python:

Многомерные массивы имеют один индекс на одну ось, поэтому обращение к элементам и извлечение срезов производится не по одному, а по нескольким индексам:

Те же правила действуют и для многомерных массивов.

Дополнительные возможности индексирования

Работая с последовательностями: строками, списками или кортежами, мы привыкли только к одному единственному способу индексирования, который предлагает нам Python.

Неужели это можно сделать как-то по другому?

Оказывается можно, и, иногда это оказывается гораздо удобнее, чем может показаться.

Помимо индексирования целыми числами и срезами, к которому мы так сильно привыкли, NumPy предлагает еще два необычных метода индексирования.

Первый - это индексация с помощью массивов целых чисел, а второй - это индексация с помощью массивов булевых значений.

Индексирование массивами целых чисел

Что такое массив индексов?

Массив индексов - это обычный массив (последовательность) целых чисел, причем каждое число соответствует некоторому индексу определенного элемента в другом массиве, например:

Но на практике гораздо удобнее использовать в качестве массивов индексов списки Python. Относительно вышеприведенного примера это будет выглядеть следующим образом:

Индексация массивами булевых значений

Булевых значений всего два, это False и True.

Возникает весьма интересный вопрос, как с помощью таких массивов выполняется индексация, ведь они состоят из одних лишь логических значиний.

И снова, оказывается не только возможно, но и крайне удобно в некоторых случаях:

Манипулирование формой массивов

Форму массива определяет количество элементов вдоль каждой оси:

Изменить форму массива можно разными способами:

Важно понимать, что функция reshape не изменяет исходный массив.

Если же вам необходимо изменить форму существующего массива, то можно воспользоваться методом resize.

Если в функции reshape один из размеров задать равным -1, то этот размер будет вычислен автоматически:

Объединение массивов

Объединение массивов возможно по разным осям:

Как видим функция vstack объединяет массивы по вертикали, а hstack - по горизонтали. Причем количество элементов вдоль объединяемых осей должно быть одинаковым.

Функция column_stack представляет одномерные массивы в виде столбцов после чего объединяет их.

Для двумерных массивов column_stack эквивалентна hstack:

Функция row_stack эквивалентна vstack для любых входных массивов:

Есть еще один способ быстро объединять и создавать массивы - это объекты r_ и c_.

Они позволяют объединить массивы вдоль одной оси или позволяют создать новый массив с использованием операций среза.

Разделение массивов

Разделить массив вдоль горизонтальной оси можно с помощью функции hsplit, а вдоль вертикальной vsplit:

Копии и представления массивов

Вы, может быть уже заметили, что некоторые функции, что-то делают с массивом, возвращают какой-то результат, но при этом с исходным массивом ничего не происходит.

Например:

Дело в том, что в NumPy существует два понятия: копия массива и представление массива.

Попробуем разобраться на примерах.

Хорошо, a и b - это адреса (указатели) одного и того же массива.

Как быть с переменной с?

По сути это тоже указатель, который ссылается на ту же самую область памяти с данными, на которую ссылаются a и b, но представлены эти данные в другой форме.

Поэтому в NumPy и существует понятие - представление массива.

Действительно, одни и те же данные могут быть представлены в разной форме:

Простое присваивание не делает никаких копий массива - это первое, о чем нужно помнить.

Поэтому отсутствие автоматического копирования при присваивании - небольшая плата за простоту и легкость Python.

Довольно часто, необходимо сделать полную копию массива и метод copy позволяет сделать это, причем скопировать не только данные массива, но и все его свойства.

Теперь мы знаем, что простое присваивание не выполняет копирования массивов.

Если нам нужна копия, то мы можем легко сделать ее с помощью метода copy.

Однако, бывают случаи когда копия массива не нужна, а нужен тот же самый массив, но с другими размерами - другое представление исходного массива.

Для таких нужд NumPy предоставляет метод ndarray.view().

Этот метод создает новый объект массива, который просматривает данные исходного массива, но изменение размеров одного массива не повлечет изменение размеров другого.

Как правило, функции меняющие форму и порядок элементов в массивах возвращают именно представление, а не копию массива:

Срезы массивов - это тоже представления массивов:

Если мы говорим, что массив b - это представление массива a, то подразумевается, что независимо от формы и вида массива b он состоит из тех же данных в памяти, что и массив a.

Поэтому изменение элементов в одном из них повлечет изменение соответствующих элементов в другом.