В предыдущей части мы рассмотрели первые 15 задач из сборника 100 задач на Github.
В данной статье мы разберём следующие 15 задач. Как и в прошлый раз я рекомендую не просто читать данную статью, а руками проделать все эти шаги и посмотреть на работу библиотеки вживую. Таким образом, данный материал лучше отпечатается в Вашей голове :)
Некоторые задачи я буду пропускать, так как описание их в данной статье не принесёт никакой пользы. Поэтому рекомендую посмотреть самостоятельно пропущенные номера задач.
Задача 16. Как добавить границу (заполненную 0) вокруг существующего массива?
Пусть есть матрица размером 5 на 5, заполненная единицами для наглядности.
Теперь, чтобы добавить нули по границам матрицы, достаточно просто воспользоваться встроенной для этого функцией numpy.pad(...):
- pad_width=1 — говорит, сколько добавлять значений. В нашем случае нужно лишь добавить одно значение по границам
- mode='constant' — говорит, что заполняем константными значениями, в нашем случае числовыми
- constant_values=0 — говорит, какими значениями заполнять, в нашем случае нулями
Также автор задач на гитхабе решил показать ещё, как можно изменить значения существующей границы numpy-массива:
В данном примере показан интересный подход с использованием срезов и индексации numpy-массивов. Давайте разберём.
- Z[:, [0, -1]] — позволяет выбрать первый и последний столбец. Если вспомнить срезы, то двоеточие на первом месте означает, что выбираются все первые индексы. А вот второй аргумент [0, -1] говорит, что в пару к каждому элементу будет выбираться элемент с индексом первого и последнего столбца (так как стоит -1). Таким образом, получаем первый и последний столбец.
- Z[[0, -1], :] — наоборот выбирает все вторые индексы и ставит им в соответствие индексы первой и последней строки.Таким образом, получаем первую и последнюю строку.
Подробнее про индексацию numpy-массивов можно прочитать тут.
Задача 18. Создать матрицу 5х5 со значениями 1,2,3,4 чуть ниже диагонали.
Для начала давайте посмотрим, что мы должны получить. Как видно есть главная диагональ матрицы и снизу её стоят нужные значения.
Рассмотрим 2 варианта решения. В numpy есть встроенная функция numpy.diag(...), которая создаёт диагональную матрицу.
Ей на вход подаётся массив (список) значений, которые данная функция размещает по диагонали.
Можно передавать как обычный список Python, так и numpy-массивы. Полученная матрица будет квадратной, размера длины входящего массива.
Однако есть и второй параметр у данной функции k.
- По умолчанию k=0. Что значит, размещать элементы входящего массива на главной диагонали матрицы.
- Если k<0, то элементы входного массива будут размещаться ниже главной диагонали. Причем на столько позиций ниже, сколько передано.
- Если k>0 , то элементы входного массива будут размещаться выше главной диагонали. Причем на столько позиций выше, сколько передано.
Покажу на примере:
Здесь k=-1, значит на одну позицию ниже главной диагонали расположились элементы массива. Обращаю внимание, что при этом размер матрицы увеличился с 4х4 до 5х5. Данная функция очень удобно и элегантно делает это для нас. Аналогично будет с размещением выше диагонали при k=1:
Автор задач на гитхабе предлагает и своё решение, используя чисто numpy-функции:
Напомню лишь, как можно получилось было массив элементов 1,2,3,4 с помощью numpy. Суммирование числа с массивом приводит к суммированию элементов массива с этим числом.
Задача 19. Создать матрицу 8х8 и заполните ее шахматным рисунком
Давайте вспомним, как выглядит шахматная доска :)
Пусть белый цвет обозначает ноль, а чёрный единица. Воспользуемся уже знакомой нам темой срезов:
- 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, которая преобразовывает плоский индекс или массив плоских индексов в кортеж массивов координат.
Так как индексация начинается с нуля, то 100-ый элемент имеет индекс 99.
Задача 21. Создать матрицу шахматной доски 8x8 с помощью функции tile
Функция numpy. tile (A , reps) строит массив, повторив массив A reps число раз.
Теперь давайте разберёмся. Для этого посмотрим на результат np.array([[0,1],[1,0]]) в следующем виде, чтобы стало понятно:
Это просто матрица 2х2, которую просто надо 4 раза повторить, чтобы построить матрицу 8х8. Поэтому reps=(4,4). То есть нужно повторить 4 раза по оси x, и 4 раза по оси y.
Задача 22. Нормализовать случайную матрицу 5х5
Создадим случайную матрицу 5х5:
Далее необходимо понимать, что значит "нормализовать матрицу". Нормализация осуществляется относительно среднего значения. Вычисляется как отношение разности между исходным значением и средней выборки к среднему квадратическому отклонению. У нормализованной матрицы средняя равна нулю (или очень близка ней), а среднее квадратическое отклонение равно 1 (или также очень близко к этому значению).
Среднее значение numpy-массива можно вычислить с помощью numpy.mean(...). Среднее квадратическое отклонение с помощью numpy.std(...).
Таким образом, получаем решение
Задача 23. Создать новый dtype, который описывает цвет как четыре байта без знака (RGBA)
С помощью встроенной функции numpy.dtype(...) создаётся новый тип:
Далее можно его использовать:
Обращаю внимание, что так как у нас тип без знаковый, то -4 преобразовалось в 252.
Задача 24. Умножьте матрицу 5х3 на матрицу 3х2 (вещественное матричное произведение)
Для этого есть встроенная функция numpy.dot(..), делающая точечное произведение двух массивов (матриц).
Также в python 3.5 был представлен новый оператор @ для матричного умножения:
Задача 25. Пусть есть одномерный массив, сделать отрицательными все элементы, которые находятся между 3 и 8.
Создадим массив:
Теперь углубимся в индексирование numpy-массивов. Индексировать и получать значения массива можно также с помощью логических выражений. Например:
Данным выражением мы получили все элементы массива, которые удовлетворяют логическому выражению. Таким образом, можно написать сразу решение:
Задача 29. Как округлить значения массива в большую сторону от нуля с плавающей точкой?
Для начала поясним, что значит в большую сторону от нуля. Это значит, если число положительное, например, 9.01, то округлить до 10 (в большую сторону от нуля, то есть вправо). Если число отрицательное, например, -4.01, то округлить до -5 (в большую сторону от нуля, то есть влево).
Создадим массив с помощью numpy.random.uniform(...):
Для решения можно взять модуль чисел (чтобы сделать положительными) и воспользоваться функцией numpy.ceil(...), чтобы округлить числа до бОльших целых.
После этого вернуть знак минуса тем числам, у которых он был. Здесь есть функция numpy.copysign(...), которая делает это для нас. На основе второго массива, меняет соответствующим элементам знак.
Также можно воспользоваться встроенными функцией numpy.where(...), которая по заданному условию выбирает либо первое, либо второе действие. Можно расценивать её, как тернарный оператор:
numpy.floor(...) — наоборот округляет в сторону меньшего целого.
Задача 30. Как найти общие значения между двумя массивами?
Для этого есть функция numpy. intersect1d(...), которая находит пересечение двух массивов:
На этом всё :) Остальные задачи рассмотрим в следующих частях.
Ставьте лайк, если статья понравилась и подписывайтесь на канал. Впереди ещё много интересного!