Библиотека NumPy в Python

Бонус-трек: почему массивы быстрее списков

Библиотека NumPy в Python

Мы часто пишем проекты для работы с большим количеством данных. Наши программы простые, но их принцип тот же, что в реальных рабочих приложениях: обработать некоторое количество информации, чтобы в итоге получить результат. Один из самых популярных инструментов в работе с BigData — библиотека NumPy. Сегодня установим её и разберём подробнее, как применять в программах.

Что такое NumPy

NumPy — это набор инструментов, написанный в основном на Python, C и Fortran. Полное название библиотеки — Numerical Python extensions, «Числовые расширения Python».

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

  • Одномерный массив выглядит просто как перечень значений в одну строку.
  • Двумерный массив, или матрица, — это как эксель-таблица, где каждое значение находится на пересечении двух измерений.
  • Трёхмерный массив состоит из трёх граней, где каждая грань будет двумерным массивом. Тогда каждое значение будет пересечением уже трёх измерений.
  • Таких граней-таблиц может быть сколько угодно много. Чем больше измерений многомерного массива, тем сложнее связаны между собой его значения.

Массивами могут быть наборы данных для исследования, машинного обучения и инженерных вычислений. Строительство, энергетика и аэрокосмическая промышленность — все они могут с пользой работать с этой информацией.

Так выглядят одномерный, двумерный и трёхмерный массивы:

Источник: medium.com

Один из примеров многомерного массива — финансовая модель бизнеса, где все показатели связаны между собой сложным и неочевидным образом. Например, увеличение закупок с отсроченным платежом поставщику позволит больше заработать в моменте, но может привести к кассовому разрыву через несколько месяцев. А увеличение цены на 30% сократит количество клиентов, но при этом увеличит прибыль за счёт того, что работы будет меньше, а доход не изменится. Какой вариант выбрать — с ходу непонятно, поэтому строят многомерные модели и много чего считают.

Зачем нужен NumPy и почему нельзя всё писать на Python

NumPy помогает Питону эффективнее работать с BigData.

Главная причина, почему Python такой популярный и удобный, — в универсальности и простоте. Вы можете установить его себе на компьютер и уже через пару часов написать первую несложную программу.

Язык заботится о том, чтобы разработчику было удобно писать: следит за памятью, сам разбирается в типах используемых данных, блокирует потенциально опасные операции. Но одновременно такие встроенные механизмы ограничивают возможности и часто мешают создать что-то действительно высоконагруженное и при этом быстрое.

Чтобы получить доступ к более мощным инструментам, в простой универсальный интерпретируемый Python можно подключить возможности, которые созданы на других языках. В этом и есть назначение NumPy: работать на Python, но при этом пользоваться удобствами быстрых компилируемых языков — C и Fortran.

Большие данные в программах структурируются и объединяются в коллекции — наборы элементов, каждый из которых работает немного по-разному. Одна из самых простых и основных коллекций в Python — списки. В списках могут находиться любые элементы. Их можно изменять, и у каждого элемента есть свой номер-индекс. По индексу можно напрямую обратиться к элементу и что-то с ним сделать.

Так выглядит список в Python:

my_list = [1, 2, 3, 4, 5]

С NumPy Python может создавать массивы — это основной объект библиотеки, который похож на стандартный список, но эффективнее. Массивы занимают меньше памяти и позволяют выполнять операции над множеством элементов одновременно, это называется векторизацией. Например, можно умножить все элементы массива на число или сложить два массива одной командой без написания циклов.

NumPy-массив будет выглядеть немного сложнее:

arr = np.array([1, 2, 3, 4, 5])

Тут пока много непонятного, но ниже мы всё разберём подробнее.

Как установить NumPy

NumPy не входит в стандартный пакет программ Python, её нужно устанавливать дополнительно. Самый простой способ сделать это — командой pip install numpy в терминале. Так Питон сможет скачать и установить сам всё что нужно.

Если вы пишете код в текстовом редакторе, то нужно открыть терминал командной строки, перейти в корневую директорию проекта и выполнить команду оттуда:

Тем, кто работает в IDE, нужно перейти на вкладку терминала и выполнить команду в нём:

Чтобы библиотека работала, её нужно импортировать в код командой import. Для более удобного использования ей можно присвоить сокращение, через которое её можно использовать. Так будет выглядеть импорт NumPy и присваивание ей общепринятого сокращения np:

import numpy as np

Создание массивов NumPy

Сначала сравним, как выглядит создание списков и массивов:

import numpy as np

# создаём список
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# создаём массив
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

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

Чтобы создать массив, нужно вызвать метод-функцию array. Для этого мы пишем принятое в коде обозначение NumPy (у нас это np) и через точку ставим название функции и круглые скобки. Круглые скобки нужны, чтобы показать, что мы именно вызываем функцию, а не просто передаём её в код как объект. Внутри круглых скобок мы передаём список, элементы которого станут элементами массива.

Правила создания многомерных массивов такие: размерность массива зависит от того, какой список мы передаём в функцию.

Нульмерный массив — список из одного элемента. Для его обозначения не нужно добавлять квадратные скобки:

arr = np.array(10)

Одномерный массив состоит из списка нульмерных списков. Это стандартный простой Python-список из нескольких значений:

arr = np.array([10, 20, 30])

Двумерный массив состоит из одномерных. Это вложенный список:

arr = np.array([['a', 'b', 'c'],
['d', 'e', 'f']])

Трёхмерный массив состоит из двумерных:

arr = np.array([[[1, 2, 3],
[4, 5, 6]],
[[1, 2, 3],
[4, 5, 6]]])

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

print(arr.ndim)

Ndim вернёт размерность. Для двумерного массива это будет число 2, для трёхмерного — 3 и так далее.

В NumPy можно создать массив без использования списков. Например:

  • np.zeros() создаёт массив нулей;
  • np.ones() создаёт массив единиц;
  • np.arange() создаёт массив с последовательностью чисел;
  • np.random.rand() создаёт массив случайных чисел.

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

Индексация и срезы в NumPy

Индексы и срезы работают с массивами так же, как с обычными Python-списками. 

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

Пример программы с получением конкретного элемента и среза:

# импортируем numpy
import numpy as np

# создаём массив
arr = np.array([10, 20, 30, 40, 50])

# вызываем элемент по индексу
print(arr[2])

# создаём многомерный массив
using = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])

# получаем конкретный элемент
# во второй строке и третьем столбце
element = using[1, 2]
print(element)

# вызываем срез со 2-го по 5-й элементы массива
print(arr[1:4])

Запускаем код и видим запрошенные элементы и срезы:

30
6
[20 30 40]

Манипуляции с массивами NumPy

После создания NumPy-массива его можно изменять разными способами, например изменять размерность, объединять с другими массивами и разделять.

Для примера изменим размерность через метод reshape и объединим два других массива с использованием функции concatenate:

# импортируем numpy
import numpy as np

# создаём массив
arr = np.array([1, 2, 3, 4, 5, 6])

# изменяем размерность массива
reshaped_arr = arr.reshape(2, 3)
# выводим результат на экран
print(reshaped_arr)

# создаём второй массив
arr2 = np.array([7, 8, 9])
# объединяем массивы
arrays = np.concatenate((arr, arr2))
# выводим результат на экран
print(arrays)

Получаем двумерный массив вместо одномерного и один объединённый:

[[1 2 3]
[4 5 6]]
[1 2 3 4 5 6 7 8 9]

Операции с массивами NumPy

NumPy даёт возможность выполнять поэлементные математические операции. Например, массивы одинакового размера можно складывать, вычитать один из другого или делить один на другой. Ещё есть поддержка операций с числами-скалярами, которые применяются ко всем элементам массива.

В примере для демонстрации сложим два массива и умножим все числа одного из них на скаляр (проще говоря, на какое-то число):

# импортируем numpy
import numpy as np

# создаём два массива
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# выполняем поэлементное сложение
# и выводим результат на экран
print(arr1 + arr2)

# умножаем на скаляр и выводим результат на экран
print(arr1 * 2)

Запускаем:

[5 7 9]
[2 4 6]

Сортировка и поиск в NumPy

Массивы можно быстро сортировать и искать в них элементы через уже существующие методы. Например, sort() сортирует массив по возрастанию, а argmax() и argmin() возвращают индексы максимального и минимального элементов:

# импортируем numpy
import numpy as np

# создаём массив
arr = np.array([3, 1, 4, 1, 5, 9])

# сортируем массив по возрастанию
sorted_arr = np.sort(arr)
# выводим результат на экран
print(sorted_arr)

# находим максимальный индекс среди элементов
print(np.argmax(arr))

Запущенный код сортирует массив и выводит его отсортированным по возрастанию. После этого программа находит максимальный индекс у элементов:

[1 1 3 4 5 9]
5

Универсальные функции (ufuncs)

Функции NumPy, которые работают с массивами поэлементно. 

Например, np.sqrt вычисляет квадратный корень каждого элемента, а np.exp — экспоненту:

# импортируем numpy
import numpy as np

# создаём массив
data = np.array([1, 4, 9, 16])

# вычисляем квадратный корень поэлементно
print(np.sqrt(data))

# вычисляем экспоненту
print(np.exp(data))

Проверяем:

[1. 2. 3. 4.]
[2.71828183e+00 5.45981500e+01 8.10308393e+03 8.88611052e+06]

Работа с изображениями в NumPy

Изображения можно представлять как многомерные массивы NumPy. Например, чёрно-белое изображение — это двумерный массив, а цветное — трёхмерный (высота × ширина × цветовые каналы). С помощью NumPy можно изменять яркость, обрезать изображения или применять фильтры.

Для примера возьмём такое изображение:

Вафля из миллиардов транзисторов. Если её разрезать в правильных местах, получатся наши микропроцессоры

Теперь напишем код, который переведёт картинку в массив и увеличит яркость:

# импортируем numpy
import numpy as np
# импортируем модуль Image из PIL
from PIL import Image

# загружаем изображения и преобразовываем их в массив
image = Image.open("image.jpg")
image_array = np.array(image)

# изменяем яркость через увеличение значения пикселей
brightened_image = image_array + 50
Image.fromarray(brightened_image).show()

Что получается при запуске кода:

Примеры использования NumPy

Сегодня NumPy применяют разные области для разных целей:

  • Data Science — для очистки данных, обработки и статистики;
  • машинное обучение — для быстрых операций с данными и обучения моделей;
  • в научных дисциплинах, например в физике, химии и биологии, NumPy используют для моделирования, симуляций и анализа данных;
  • компьютерное зрение — для обработки изображений;
  • в финансах NumPy применяют для анализа временных рядов, расчёта рисков и моделирования портфелей.

Вам слово

Приходите к нам в соцсети поделиться своим мнением о статье и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!

Обложка:

Алексей Сухов

Корректор:

Александр Зубов

Вёрстка:

Кирилл Климентьев

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
А вы читали это?
hard
[anycomment]
Exit mobile version