Найти тему
Сам себе Data Scientist

Учим NumPy на практике. Часть 2

Оглавление

В предыдущей части мы рассмотрели первые 15 задач из сборника 100 задач на Github.

В данной статье мы разберём следующие 15 задач. Как и в прошлый раз я рекомендую не просто читать данную статью, а руками проделать все эти шаги и посмотреть на работу библиотеки вживую. Таким образом, данный материал лучше отпечатается в Вашей голове :)

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

Задача 16. Как добавить границу (заполненную 0) вокруг существующего массива?

Пусть есть матрица размером 5 на 5, заполненная единицами для наглядности.

-2

Теперь, чтобы добавить нули по границам матрицы, достаточно просто воспользоваться встроенной для этого функцией numpy.pad(...):

-3
  • pad_width=1 — говорит, сколько добавлять значений. В нашем случае нужно лишь добавить одно значение по границам
  • mode='constant' — говорит, что заполняем константными значениями, в нашем случае числовыми
  • constant_values=0 — говорит, какими значениями заполнять, в нашем случае нулями

Также автор задач на гитхабе решил показать ещё, как можно изменить значения существующей границы numpy-массива:

-4

В данном примере показан интересный подход с использованием срезов и индексации numpy-массивов. Давайте разберём.

  • Z[:, [0, -1]] — позволяет выбрать первый и последний столбец. Если вспомнить срезы, то двоеточие на первом месте означает, что выбираются все первые индексы. А вот второй аргумент [0, -1] говорит, что в пару к каждому элементу будет выбираться элемент с индексом первого и последнего столбца (так как стоит -1). Таким образом, получаем первый и последний столбец.
-5
  • Z[[0, -1], :] — наоборот выбирает все вторые индексы и ставит им в соответствие индексы первой и последней строки.Таким образом, получаем первую и последнюю строку.
-6

Подробнее про индексацию numpy-массивов можно прочитать тут.

Задача 18. Создать матрицу 5х5 со значениями 1,2,3,4 чуть ниже диагонали.

Для начала давайте посмотрим, что мы должны получить. Как видно есть главная диагональ матрицы и снизу её стоят нужные значения.

-7

Рассмотрим 2 варианта решения. В numpy есть встроенная функция numpy.diag(...), которая создаёт диагональную матрицу.

Ей на вход подаётся массив (список) значений, которые данная функция размещает по диагонали.

-8

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

Однако есть и второй параметр у данной функции k.

  • По умолчанию k=0. Что значит, размещать элементы входящего массива на главной диагонали матрицы.
  • Если k<0, то элементы входного массива будут размещаться ниже главной диагонали. Причем на столько позиций ниже, сколько передано.
  • Если k>0 , то элементы входного массива будут размещаться выше главной диагонали. Причем на столько позиций выше, сколько передано.

Покажу на примере:

-9

Здесь k=-1, значит на одну позицию ниже главной диагонали расположились элементы массива. Обращаю внимание, что при этом размер матрицы увеличился с 4х4 до 5х5. Данная функция очень удобно и элегантно делает это для нас. Аналогично будет с размещением выше диагонали при k=1:

-10

Автор задач на гитхабе предлагает и своё решение, используя чисто numpy-функции:

-11

Напомню лишь, как можно получилось было массив элементов 1,2,3,4 с помощью numpy. Суммирование числа с массивом приводит к суммированию элементов массива с этим числом.

-12

Задача 19. Создать матрицу 8х8 и заполните ее шахматным рисунком

Давайте вспомним, как выглядит шахматная доска :)

-13

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

-14
  • Z[1::2,::2] — выберет все строки, начиная со второй (так как индекс 1 первым параметром) и с шагом 2, то есть через одну строки будут браться. И в соответствие поставит столбцы, начиная с первого через один (так как шаг указан 2 во втором параметре среза). То есть если смотреть на доску выше, будут выбраны строки 7,5,3,1 и столбцы A,C,E,G
  • Z[::2,1::2] — выберет все строки, начиная с первой и с шагом 2, то есть через одну строки будут браться. И в соответствие поставит столбцы, начиная со второго (индекс 1) через один (так как шаг указан 2 во втором параметре среза). То есть если смотреть на доску выше, будут выбраны строки 8,6,4,2 и столбцы B,D,F,H

Задача 20. Рассмотрим массив форм (6,7,8), каков индекс (x,y,z) 100-го элемента?

Для этого есть встроенная функция numpy. unravel_index, которая преобразовывает плоский индекс или массив плоских индексов в кортеж массивов координат.

-15

Так как индексация начинается с нуля, то 100-ый элемент имеет индекс 99.

Задача 21. Создать матрицу шахматной доски 8x8 с помощью функции tile

Функция numpy. tile (A , reps) строит массив, повторив массив A reps число раз.

-16

Теперь давайте разберёмся. Для этого посмотрим на результат np.array([[0,1],[1,0]]) в следующем виде, чтобы стало понятно:

-17

Это просто матрица 2х2, которую просто надо 4 раза повторить, чтобы построить матрицу 8х8. Поэтому reps=(4,4). То есть нужно повторить 4 раза по оси x, и 4 раза по оси y.

Задача 22. Нормализовать случайную матрицу 5х5

Создадим случайную матрицу 5х5:

-18

Далее необходимо понимать, что значит "нормализовать матрицу". Нормализация осуществляется относительно среднего значения. Вычисляется как отношение разности между исходным значением и средней выборки к среднему квадратическому отклонению. У нормализованной матрицы средняя равна нулю (или очень близка ней), а среднее квадратическое отклонение равно 1 (или также очень близко к этому значению).

Среднее значение numpy-массива можно вычислить с помощью numpy.mean(...). Среднее квадратическое отклонение с помощью numpy.std(...).

Таким образом, получаем решение

-19

Задача 23. Создать новый dtype, который описывает цвет как четыре байта без знака (RGBA)

С помощью встроенной функции numpy.dtype(...) создаётся новый тип:

-20

Далее можно его использовать:

-21
-22

Обращаю внимание, что так как у нас тип без знаковый, то -4 преобразовалось в 252.

Задача 24. Умножьте матрицу 5х3 на матрицу 3х2 (вещественное матричное произведение)

Для этого есть встроенная функция numpy.dot(..), делающая точечное произведение двух массивов (матриц).

-23

Также в python 3.5 был представлен новый оператор @ для матричного умножения:

-24

Задача 25. Пусть есть одномерный массив, сделать отрицательными все элементы, которые находятся между 3 и 8.

Создадим массив:

-25

Теперь углубимся в индексирование numpy-массивов. Индексировать и получать значения массива можно также с помощью логических выражений. Например:

-26

Данным выражением мы получили все элементы массива, которые удовлетворяют логическому выражению. Таким образом, можно написать сразу решение:

-27

Задача 29. Как округлить значения массива в большую сторону от нуля с плавающей точкой?

Для начала поясним, что значит в большую сторону от нуля. Это значит, если число положительное, например, 9.01, то округлить до 10 (в большую сторону от нуля, то есть вправо). Если число отрицательное, например, -4.01, то округлить до -5 (в большую сторону от нуля, то есть влево).

Создадим массив с помощью numpy.random.uniform(...):

-28

Для решения можно взять модуль чисел (чтобы сделать положительными) и воспользоваться функцией numpy.ceil(...), чтобы округлить числа до бОльших целых.

-29

После этого вернуть знак минуса тем числам, у которых он был. Здесь есть функция numpy.copysign(...), которая делает это для нас. На основе второго массива, меняет соответствующим элементам знак.

-30

Также можно воспользоваться встроенными функцией numpy.where(...), которая по заданному условию выбирает либо первое, либо второе действие. Можно расценивать её, как тернарный оператор:

-31

numpy.floor(...) — наоборот округляет в сторону меньшего целого.

Задача 30. Как найти общие значения между двумя массивами?

Для этого есть функция numpy. intersect1d(...), которая находит пересечение двух массивов:

-32

На этом всё :) Остальные задачи рассмотрим в следующих частях.

Ставьте лайк, если статья понравилась и подписывайтесь на канал. Впереди ещё много интересного!