NumPy для продвинутых: Как эффективно манипулировать данными в Python?

Краткий обзор NumPy и его значимости для манипулирования данными

NumPy – это фундаментальная библиотека для научных вычислений в Python. Она предоставляет мощные инструменты для работы с многомерными массивами и матрицами, а также содержит оптимизированные математические функции для выполнения операций над этими массивами. NumPy лежит в основе многих других библиотек анализа данных, таких как pandas и scikit-learn, что делает ее знание необходимым для любого, кто занимается анализом данных в Python. Основная ценность NumPy заключается в предоставлении эффективных и быстрых способов манипулирования большими объемами данных, что критически важно для задач машинного обучения, статистики и других областей.

Предполагаемый уровень подготовки читателя: что нужно знать перед началом

Эта статья предназначена для читателей, уже знакомых с основами NumPy. Предполагается, что вы понимаете концепции массивов NumPy, знаете, как создавать массивы, выполнять базовые операции над ними (сложение, умножение и т.д.), и знакомы с индексированием и слайсингом. Базовое понимание Python и основных структур данных (списки, словари) также необходимо. Если вы новичок в NumPy, рекомендуется сначала ознакомиться с базовыми учебниками и документацией.

Цели статьи: что вы узнаете и сможете делать после прочтения

После прочтения этой статьи вы:

  1. Освоите продвинутые методы индексирования и выборки данных в NumPy.
  2. Поймете принципы векторизации и широковещания (broadcasting) и научитесь применять их для оптимизации кода.
  3. Узнаете, как эффективно работать с многомерными массивами и осями.
  4. Ознакомитесь с продвинутыми математическими и статистическими функциями NumPy.
  5. Сможете применять полученные знания для решения практических задач манипулирования данными.

Эффективное индексирование и выборка данных в NumPy

Продвинутое индексирование: целочисленное и булево индексирование

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

import numpy as np

# Целочисленное индексирование
arr = np.array([10, 20, 30, 40, 50])
indices = [0, 2, 4]
selected_elements = arr[indices]  # [10 30 50]

# Булево индексирование
arr = np.array([5, 10, 15, 20, 25])
mask = arr > 12  # [False False  True  True  True]
filtered_elements = arr[mask]  # [15 20 25]

print(f'{selected_elements=}')
print(f'{filtered_elements=}')

Использование np.where для условной выборки данных

Функция np.where позволяет выбирать элементы из одного массива на основе условия, заданного в другом массиве. Это полезно для замены значений в массиве на основе определенных критериев.

import numpy as np

# Пример использования np.where
arr = np.array([1, 2, 3, 4, 5])

# Заменяем значения меньше 3 на -1, а остальные оставляем без изменений
new_arr = np.where(arr < 3, -1, arr)

print(f'{new_arr=}') # [-1 -1  3  4  5]

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

Маски – это булевы массивы, которые используются для выбора элементов, удовлетворяющих сложным условиям. Маски можно создавать с использованием логических операторов (&, |, ~) для объединения нескольких условий.

import numpy as np

# Пример использования масок
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# Создаем маску для чисел, которые больше 2 И меньше 8
mask = (arr > 2) & (arr < 8)

filtered_arr = arr[mask]

print(f'{filtered_arr=}') # [3 4 5 6 7]

Индексирование с использованием np.take и np.put

np.take позволяет выбирать элементы из массива по заданным индексам, а np.put позволяет заменять элементы массива по заданным индексам. Эти функции особенно полезны при работе с большими массивами, где важна производительность.

import numpy as np

# Пример использования np.take
arr = np.array([10, 20, 30, 40, 50])
indices = [0, 2, 4]
selected_elements = np.take(arr, indices)  # [10 30 50]

# Пример использования np.put
arr = np.array([1, 2, 3, 4, 5])
indices = [0, 2, 4]
values = [100, 200, 300]
np.put(arr, indices, values)

print(f'{arr=}') # [100   2 200   4 300]

Векторизация и широковещание (Broadcasting) в NumPy

Принцип векторизации: как избежать циклов Python

Векторизация – это процесс замены явных циклов в коде операциями над массивами NumPy. Векторизованные операции выполняются значительно быстрее, чем эквивалентные операции, реализованные с использованием циклов Python, поскольку они реализованы на C и используют оптимизированные алгоритмы. Использование векторизации значительно повышает производительность кода.

Подробное рассмотрение правил широковещания (broadcasting rules)

Широковещание (broadcasting) – это механизм, позволяющий NumPy выполнять операции над массивами разной формы. NumPy автоматически расширяет меньший массив, чтобы он соответствовал форме большего массива, прежде чем выполнить операцию. Правила широковещания:

  1. Если два массива имеют разное количество измерений, форма массива с меньшим количеством измерений дополняется единицами слева.
  2. Если форма двух массивов не совпадает в каком-то измерении, массив с формой 1 в этом измерении расширяется, чтобы соответствовать форме другого массива.
  3. Если в каком-то измерении ни один из массивов не имеет форму 1, и формы не совпадают, возникает ошибка.

Практические примеры использования broadcasting для сложных вычислений

import numpy as np

# Пример broadcasting
arr1 = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
arr2 = np.array([10, 20, 30]) # (3,)

result = arr1 + arr2  # arr2 будет расширен до [[10, 20, 30], [10, 20, 30]]

print(f'{result=}')
import numpy as np

# Допустим, у вас есть данные о расходах на рекламу в разных каналах (например, контекстная реклама, таргетированная реклама, email-маркетинг) за несколько дней.
advertising_costs = np.array([
    [100, 150, 200],  # Расходы в день 1
    [120, 180, 240],  # Расходы в день 2
    [110, 165, 220]   # Расходы в день 3
])

# И есть информация о средней конверсии каждого канала (например, процент пользователей, которые совершили покупку после просмотра рекламы).
conversion_rates = np.array([0.02, 0.03, 0.05])  # Конверсия для контекстной, таргетированной и email-рекламы

# Вы хотите рассчитать ожидаемое количество конверсий для каждого дня и каждого канала. С помощью broadcasting можно сделать это очень просто:
expected_conversions = advertising_costs * conversion_rates

# broadcasting произойдет следующим образом:
# conversion_rates  [0.02, 0.03, 0.05]  -> [[0.02, 0.03, 0.05], [0.02, 0.03, 0.05], [0.02, 0.03, 0.05]]

print(f'{expected_conversions=}')
# [[2.  4.5 10. ]
#  [2.4 5.4 12. ]
#  [2.2 4.95 11. ]] - ожидаемое количество конверсий для каждого дня и канала.
Реклама

Оптимизация производительности с помощью векторизованных операций

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

Работа с многомерными массивами и осями в NumPy

Изменение формы массивов: reshape, flatten, ravel

reshape позволяет изменить форму массива без изменения его данных. flatten создает одномерную копию массива. ravel также создает одномерный вид массива, но может возвращать представление (view) исходного массива, если это возможно.

import numpy as np

# Пример использования reshape
arr = np.array([1, 2, 3, 4, 5, 6])
reshaped_arr = arr.reshape((2, 3))

# Пример использования flatten
multi_arr = np.array([[1, 2, 3], [4, 5, 6]])
flattened_arr = multi_arr.flatten()

# Пример использования ravel
raveled_arr = multi_arr.ravel()

print(f'{reshaped_arr=}')
print(f'{flattened_arr=}')
print(f'{raveled_arr=}')

Транспонирование массивов и перестановка осей: transpose и swapaxes

transpose меняет порядок осей массива. Для двумерных массивов это эквивалентно транспонированию матрицы. swapaxes меняет местами две указанные оси.

import numpy as np

# Пример использования transpose
arr = np.array([[1, 2, 3], [4, 5, 6]])
transposed_arr = arr.transpose()

# Пример использования swapaxes
swapped_arr = arr.swapaxes(0, 1)

print(f'{transposed_arr=}')
print(f'{swapped_arr=}')

Выполнение операций по осям: sum, mean, max с аргументом axis

Функции sum, mean, max и другие могут быть применены к массиву по определенной оси с использованием аргумента axis. Это позволяет выполнять операции вдоль строк или столбцов в многомерных массивах.

import numpy as np

# Пример использования axis
arr = np.array([[1, 2, 3], [4, 5, 6]])
sum_rows = arr.sum(axis=0)  # Сумма по столбцам
sum_cols = arr.sum(axis=1)  # Сумма по строкам

print(f'{sum_rows=}')
print(f'{sum_cols=}')

Соединение и разделение массивов: concatenate, stack, split

concatenate позволяет объединять массивы вдоль существующей оси. stack создает новый массив, объединяя массивы вдоль новой оси. split разделяет массив на несколько подмассивов.

import numpy as np

# Пример использования concatenate
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
concatenated_arr = np.concatenate((arr1, arr2))

# Пример использования stack
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
stacked_arr = np.stack((arr1, arr2))

# Пример использования split
arr = np.array([1, 2, 3, 4, 5, 6])
split_arr = np.split(arr, 3)  # Разбиваем на 3 подмассива

print(f'{concatenated_arr=}')
print(f'{stacked_arr=}')
print(f'{split_arr=}')

Продвинутые математические и статистические функции NumPy

Линейная алгебра с NumPy: решение систем уравнений, вычисление собственных значений

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

import numpy as np

# Решение системы линейных уравнений
a = np.array([[2, 1], [1, 3]])
b = np.array([5, 8])
x = np.linalg.solve(a, b)

# Вычисление собственных значений и векторов
a = np.array([[1, 2], [3, 4]])
w, v = np.linalg.eig(a)

print(f'{x=}')
print(f'{w=}')
print(f'{v=}')

Преобразование Фурье с использованием np.fft

np.fft позволяет выполнять преобразование Фурье над массивами. Преобразование Фурье используется для анализа частотных характеристик сигналов и изображений.

import numpy as np

# Пример использования FFT
signal = np.array([1, 2, 3, 4])
fft_result = np.fft.fft(signal)

print(f'{fft_result=}')

Случайные числа и распределения: генерация и использование в моделировании

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

import numpy as np

# Генерация случайных чисел
random_numbers = np.random.rand(5)  # 5 случайных чисел от 0 до 1
normal_numbers = np.random.normal(0, 1, 5)  # 5 случайных чисел из нормального распределения

print(f'{random_numbers=}')
print(f'{normal_numbers=}')
import numpy as np
import matplotlib.pyplot as plt

# Допустим, у вас есть данные о кликах на рекламное объявление в течение определенного периода времени.
# Вы хотите смоделировать количество кликов в будущем, используя распределение Пуассона, которое часто используется для моделирования событий, происходящих случайно во времени.

# Параметр lambda (среднее количество событий за период времени)
lambda_param = 5  # Среднее количество кликов в день

# Количество дней, которые мы хотим смоделировать
num_days = 100

# Генерируем случайные числа из распределения Пуассона
clicks_per_day = np.random.poisson(lambda_param, num_days)

# Теперь у вас есть массив clicks_per_day, содержащий случайные значения, представляющие количество кликов на рекламу каждый из 100 дней.
# Вы можете использовать эти данные для анализа и прогнозирования.

# Например, можно построить гистограмму для визуализации распределения кликов:
plt.hist(clicks_per_day, bins=15, density=True, alpha=0.6, color='g')
plt.xlabel('Количество кликов в день')
plt.ylabel('Вероятность')
plt.title('Распределение Пуассона: Клики на рекламу')
plt.show()

# Или рассчитать среднее и стандартное отклонение:
mean_clicks = np.mean(clicks_per_day)
std_clicks = np.std(clicks_per_day)

print(f'{mean_clicks=}')
print(f'{std_clicks=}')

Статистические функции: квантили, корреляции, гистограммы

NumPy предоставляет широкий набор статистических функций, таких как вычисление квантилей, корреляций, построение гистограмм и т.д. Эти функции позволяют анализировать и понимать данные.

import numpy as np

# Статистические функции
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
quantile = np.quantile(arr, 0.5)  # Медиана
correlation = np.corrcoef(arr[:-1], arr[1:])  # Корреляция между соседними элементами
histogram, bins = np.histogram(arr, bins=5)  # Гистограмма

print(f'{quantile=}')
print(f'{correlation=}')
print(f'{histogram=}')
print(f'{bins=}')

Добавить комментарий