Введение в NumPy для анализа данных
Что такое NumPy и почему он важен для анализа данных в Python?
NumPy (Numerical Python) — это фундаментальная библиотека для научных вычислений в Python. Её ключевой особенностью являются многомерные массивы (ndarray), обеспечивающие эффективное хранение и манипулирование числовыми данными. NumPy важен для анализа данных, потому что он:
- Оптимизирован для численных операций: NumPy предоставляет векторизованные операции, которые выполняются значительно быстрее, чем стандартные циклы Python. Это особенно важно при работе с большими объемами данных.
- Основа для других библиотек: Pandas, SciPy, scikit-learn и многие другие библиотеки анализа данных построены на основе NumPy, используя его массивы как базовую структуру данных.
- Удобство и выразительность: NumPy предлагает мощные инструменты для индексации, срезов, маскирования и других операций над массивами, делая код более читаемым и лаконичным.
Установка NumPy: пошаговая инструкция
Установить NumPy можно с помощью pip
:
pip install numpy
Или с помощью conda
:
conda install numpy
После установки импортируйте библиотеку в свой скрипт:
import numpy as np
Основные типы данных в NumPy: массивы (ndarray)
Основной тип данных в NumPy — это ndarray
(n-dimensional array). Массив NumPy представляет собой сетку значений, все одного типа, индексируемую кортежем неотрицательных целых чисел. Количество измерений массива называется рангом, а форма массива — это кортеж, указывающий размер массива по каждому измерению.
Создание и манипулирование массивами NumPy
Создание массивов NumPy различными способами (np.array, np.zeros, np.ones, np.arange, np.linspace)
-
np.array()
: Создает массив из списка или кортежа Python.import numpy as np data: list[int] = [1, 2, 3, 4, 5] arr: np.ndarray = np.array(data) print(arr) # Вывод: [1 2 3 4 5]
-
np.zeros()
: Создает массив, заполненный нулями.zeros_arr: np.ndarray = np.zeros((2, 3)) print(zeros_arr) # Вывод: # [[0. 0. 0.] # [0. 0. 0.]]
-
np.ones()
: Создает массив, заполненный единицами.ones_arr: np.ndarray = np.ones((3, 2)) print(ones_arr) # Вывод: # [[1. 1.] # [1. 1.] # [1. 1.]]
-
np.arange()
: Создает массив с последовательностью чисел в заданном диапазоне.range_arr: np.ndarray = np.arange(0, 10, 2) # от 0 до 10 (не включая) с шагом 2 print(range_arr) # Вывод: [0 2 4 6 8]
-
np.linspace()
: Создает массив с заданным количеством чисел, равномерно распределенных в заданном диапазоне.linspace_arr: np.ndarray = np.linspace(0, 1, 5) # 5 чисел от 0 до 1 включительно print(linspace_arr) # Вывод: [0. 0.25 0.5 0.75 1. ]
Изменение формы массивов (reshape)
Метод reshape()
позволяет изменить форму массива, не меняя его данные.
arr: np.ndarray = np.arange(12)
reshaped_arr: np.ndarray = arr.reshape((3, 4)) # Преобразование в массив 3x4
print(reshaped_arr)
# Вывод:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
Индексация и срезы массивов: доступ к элементам и подмассивам
Индексация и срезы в NumPy аналогичны индексации и срезам списков Python, но с расширенными возможностями для многомерных массивов.
arr: np.ndarray = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
element: int = arr[0, 1] # Доступ к элементу в строке 0, столбце 1 (значение 2)
print(f'{element=}')
subarray: np.ndarray = arr[0:2, 1:3] # Срез: первые две строки, столбцы с 1 по 2
print(f'{subarray=}')
# Вывод:
# subarray=array([[2, 3],
# [5, 6]])
Объединение и разделение массивов (concatenate, stack, split)
np.concatenate()
: Объединяет массивы вдоль указанной оси.np.stack()
: Создает новый массив, объединяя массивы вдоль новой оси.np.split()
: Разделяет массив на несколько подмассивов.
arr1: np.ndarray = np.array([[1, 2], [3, 4]])
arr2: np.ndarray = np.array([[5, 6], [7, 8]])
concatenated_arr: np.ndarray = np.concatenate((arr1, arr2), axis=0) # Объединение по строкам
print(f'{concatenated_arr=}')
# concatenated_arr=array([[1, 2],
# [3, 4],
# [5, 6],
# [7, 8]])
stacked_arr: np.ndarray = np.stack((arr1, arr2), axis=0) # Объединение по новой оси
print(f'{stacked_arr=}')
# stacked_arr=array([[[1, 2],
# [3, 4]],
#
# [[5, 6],
# [7, 8]]])
split_arrs: list[np.ndarray] = np.split(arr1, 2, axis=0) # Разделение на 2 подмассива по строкам
print(f'{split_arrs=}')
# split_arrs=[array([[1, 2]]), array([[3, 4]])]
Операции над массивами NumPy
Арифметические операции: поэлементное сложение, вычитание, умножение, деление
NumPy выполняет арифметические операции поэлементно. Это значит, что операция применяется к каждому элементу массива.
arr1: np.ndarray = np.array([1, 2, 3])
arr2: np.ndarray = np.array([4, 5, 6])
sum_arr: np.ndarray = arr1 + arr2 # Поэлементное сложение
print(f'{sum_arr=}') # sum_arr=array([5, 7, 9])
diff_arr: np.ndarray = arr2 - arr1 # Поэлементное вычитание
print(f'{diff_arr=}') # diff_arr=array([3, 3, 3])
mul_arr: np.ndarray = arr1 * arr2 # Поэлементное умножение
print(f'{mul_arr=}') # mul_arr=array([ 4, 10, 18])
div_arr: np.ndarray = arr2 / arr1 # Поэлементное деление
print(f'{div_arr=}') # div_arr=array([4. , 2.5 , 2. ])
Матричные операции: умножение матриц, транспонирование
NumPy предоставляет функции для выполнения матричных операций.
np.dot()
: Умножение матриц.arr.T
: Транспонирование матрицы.
arr1: np.ndarray = np.array([[1, 2], [3, 4]])
arr2: np.ndarray = np.array([[5, 6], [7, 8]])
dot_arr: np.ndarray = np.dot(arr1, arr2) # Матричное умножение
print(f'{dot_arr=}')
# dot_arr=array([[19, 22],
# [43, 50]])
transposed_arr: np.ndarray = arr1.T # Транспонирование
print(f'{transposed_arr=}')
# transposed_arr=array([[1, 3],
# [2, 4]])
Универсальные функции (ufuncs): применение функций к каждому элементу массива
Универсальные функции (ufuncs) — это функции, которые выполняют поэлементные операции над массивами NumPy. NumPy предоставляет большой набор встроенных ufuncs, таких как np.sin()
, np.exp()
, np.log()
и другие.
arr: np.ndarray = np.array([0, 1, 2, 3])
sin_arr: np.ndarray = np.sin(arr) # Поэлементный синус
print(f'{sin_arr=}') # sin_arr=array([ 0. , 0.84147098, 0.90929743, 0.14112001])
exp_arr: np.ndarray = np.exp(arr) # Поэлементная экспонента
print(f'{exp_arr=}') # exp_arr=array([ 1. , 2.71828183, 7.3890561 , 20.08553692])
Логические операции и маскирование массивов
NumPy позволяет выполнять логические операции над массивами и использовать маскирование для выбора элементов, удовлетворяющих определенным условиям.
arr: np.ndarray = np.array([1, 2, 3, 4, 5])
mask: np.ndarray = arr > 2 # Создание маски: True для элементов > 2
print(f'{mask=}') # mask=array([False, False, True, True, True])
filtered_arr: np.ndarray = arr[mask] # Применение маски для выбора элементов
print(f'{filtered_arr=}') # filtered_arr=array([3, 4, 5])
NumPy для статистического анализа данных
Вычисление статистических показателей: среднее, медиана, стандартное отклонение, дисперсия
NumPy предоставляет функции для вычисления основных статистических показателей.
np.mean()
: Среднее значение.np.median()
: Медиана.np.std()
: Стандартное отклонение.np.var()
: Дисперсия.
data: np.ndarray = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
mean_value: float = np.mean(data)
print(f'{mean_value=}') # mean_value=5.5
median_value: float = np.median(data)
print(f'{median_value=}') # median_value=5.5
std_value: float = np.std(data)
print(f'{std_value=}') # std_value=2.8722813232690143
var_value: float = np.var(data)
print(f'{var_value=}') # var_value=8.25
Работа с пропущенными данными (NaN) в NumPy
NumPy позволяет представлять пропущенные данные с помощью np.nan
(Not a Number) и предоставляет функции для работы с ними.
data: np.ndarray = np.array([1, 2, np.nan, 4, 5])
is_nan_mask: np.ndarray = np.isnan(data) # Создание маски для NaN
print(f'{is_nan_mask=}') # is_nan_mask=array([False, False, True, False, False])
data_without_nan: np.ndarray = data[~is_nan_mask] # Удаление NaN
print(f'{data_without_nan=}') # data_without_nan=array([1., 2., 4., 5.])
Сортировка массивов
NumPy предоставляет функции для сортировки массивов.
np.sort()
: Возвращает отсортированную копию массива.arr.sort()
: Сортирует массив на месте.np.argsort()
: Возвращает индексы, которые отсортировали бы массив.
data: np.ndarray = np.array([5, 2, 8, 1, 9, 4])
sorted_data: np.ndarray = np.sort(data) # Сортировка и создание нового массива
print(f'{sorted_data=}') # sorted_data=array([1, 2, 4, 5, 8, 9])
indices: np.ndarray = np.argsort(data) # Получение индексов отсортированного массива
print(f'{indices=}') # indices=array([3, 1, 5, 0, 2, 4])
NumPy и Pandas: интеграция для эффективного анализа данных
Преобразование данных между NumPy массивами и Pandas DataFrame/Series
Pandas DataFrame и Series могут быть легко преобразованы в NumPy массивы и обратно.
df.to_numpy()
: Преобразование DataFrame в NumPy массив.pd.DataFrame(arr)
: Создание DataFrame из NumPy массива.
import pandas as pd
data: dict[str, list[int]] = {'col1': [1, 2, 3], 'col2': [4, 5, 6]}
df: pd.DataFrame = pd.DataFrame(data)
arr: np.ndarray = df.to_numpy()
print(f'{arr=}')
# arr=array([[1, 4],
# [2, 5],
# [3, 6]])
df_from_arr: pd.DataFrame = pd.DataFrame(arr, columns=['A', 'B'])
print(f'{df_from_arr=}')
# df_from_arr= A B
# 0 1 4
# 1 2 5
# 2 3 6
Использование NumPy для оптимизации операций в Pandas
NumPy может использоваться для оптимизации операций в Pandas, особенно при работе с большими объемами данных. Например, можно применять NumPy-функции напрямую к столбцам DataFrame.
import pandas as pd
import numpy as np
data: dict[str, list[int]] = {'clicks': [100, 150, 200, 120, 180]}
df: pd.DataFrame = pd.DataFrame(data)
# Вместо цикла по DataFrame, применяем NumPy функцию к столбцу
df['clicks_log'] = np.log(df['clicks'])
print(df)
# clicks clicks_log
# 0 100 4.605170
# 1 150 5.010635
# 2 200 5.298317
# 3 120 4.787492
# 4 180 5.192957
Примеры анализа данных с использованием NumPy и Pandas в связке
Предположим, у нас есть данные о показах и кликах рекламной кампании в Pandas DataFrame. Мы можем использовать NumPy для вычисления CTR (Click-Through Rate) и других метрик.
import pandas as pd
import numpy as np
data: dict[str, list[int]] = {
'impressions': [1000, 1500, 2000, 1200, 1800],
'clicks': [100, 150, 200, 120, 180]
}
df: pd.DataFrame = pd.DataFrame(data)
# Вычисление CTR с использованием NumPy
df['ctr'] = df['clicks'] / df['impressions']
# Вычисление среднего CTR
mean_ctr: float = np.mean(df['ctr'])
print(f'{mean_ctr=}')
print(df)
# impressions clicks ctr
# 0 1000 100 0.10
# 1 1500 150 0.10
# 2 2000 200 0.10
# 3 1200 120 0.10
# 4 1800 180 0.10