Инструменты научных вычислений: массивы и таблицы в Python

Раздел: Машинное обучение -> NumPy и Pandas

Эффективное использование NumPy и Pandas

Как оптимально обрабатывать табличные данные с числовыми массивами?

Наиболее продуктивный подход заключается в совместном применении NumPy для операций над многомерными массивами и Pandas для структурированных таблиц с метками. Таким образом можно выполнять векторизованные вычисления, не прибегая к циклам Python. Например, сначала загружаются данные в DataFrame, затем извлекаются столбцы как массивы NumPy для математических расчетов, после чего результат снова интегрируется в таблицу.

import numpy as np
import pandas as pd

df = pd.read_csv('data.csv')
array = df['price'].to_numpy()  # преобразование в массив NumPy
mean_price = np.mean(array)
df['price_normalized'] = (array - mean_price) / np.std(array)

Python numpy pandas (numpy и pandas в python)

Пояснение: загрузка данных выполняется одной строкой Pandas, затем столбец конвертируется в массив для векторизованной нормализации. Результат сохраняется как новый столбец DataFrame.

Типичные ошибки:

  • Попытка напрямую умножить DataFrame на число – Pandas делает это поэлементно, но при смешивании типов может возникнуть неявное приведение. Рекомендуется использовать .to_numpy() для явного контроля.
  • Забывание про пропущенные значения. NumPy не поддерживает NaN по умолчанию в целочисленных массивах. Перед конвертацией следует удалить или заполнить пропуски.
  • Использование циклов для обработки строк – это в десятки раз медленнее векторизованных операций.

Как выполнить фильтрацию данных с использованием только Pandas?

Если задача не требует интенсивных численных расчетов, достаточно возможностей Pandas. Логическая индексация и методы .query() позволяют выбирать строки по условиям.

import pandas as pd

df = pd.DataFrame({'A': [1,2,3], 'B': [10,20,30]})
filtered = df[df['A'] > 1]  # строки, где A > 1
# или с query:
filtered2 = df.query('A > 1 and B < 25')

Фильтрация не создает копию данных, а возвращает представление. Однако изменение отфильтрованного набора может повлиять на исходный DataFrame – это стоит учитывать.

Проблема:

Цепочка операций с копиями может приводить к неожиданным результатам. Используйте .copy() перед модификацией.

Как создать массив NumPy с заданной структурой?

NumPy предоставляет функции np.zeros, np.ones, np.arange, np.linspace для быстрой генерации массивов.

import numpy as np

a = np.zeros((3,4))          # матрица 3x4 из нулей
b = np.ones((2,3,2))         # трёхмерный массив из единиц
c = np.arange(0, 10, 2)      # [0,2,4,6,8]
d = np.linspace(0, 1, 5)     # [0, 0.25, 0.5, 0.75, 1.]

Пояснение: arange генерирует последовательность с заданным шагом, linspace – равномерное распределение на отрезке. Все функции поддерживают тип данных через параметр dtype.

Ошибка:

При использовании np.arange с нецелым шагом возможны погрешности из-за арифметики с плавающей запятой. Для равномерной сетки лучше применять linspace.

Как объединить несколько таблиц с разной структурой?

Pandas поддерживает SQL-подобные операции слияния через pd.merge(). Это мощнее, чем конкатенация, так как учитывает ключи.

import pandas as pd

orders = pd.DataFrame({'order_id': [1,2], 'customer_id': [101,102]})
customers = pd.DataFrame({'id': [101,102], 'name': ['Alice','Bob']})
merged = pd.merge(orders, customers, left_on='customer_id', right_on='id', how='inner')
print(merged)

Результат: объединенная таблица с именем клиента. Параметр how определяет тип соединения (inner, outer, left, right).

Типичная ошибка:

Несовпадение типов ключей (строка против числа) приводит к пустому результату. Перед слиянием следует привести ключи к одному типу.

Расширенные примеры применения NumPy и Pandas

Пример
import numpy as np
import pandas as pd

# Векторизованная замена значений в DataFrame на основе условия
np.random.seed(42)
df = pd.DataFrame(np.random.randn(5,3), columns=['A','B','C'])
df['D'] = np.where(df['A'] > 0, 'positive', 'negative')
print('Исходный DataFrame:')
print(df.head())

# Вывод результата:
#           A         B         C         D
# 0  0.496714  0.861736  0.028766  positive
# 1 -0.234153 -0.398063 -0.510058  negative
# 2 -0.239048  0.406690  0.142977  negative
# 3  0.294284  0.779050  0.284340  positive
# 4 -0.871038 -0.202532 -0.007785  negative
          A         B         C         D
0  0.496714  0.861736  0.028766  positive
1 -0.234153 -0.398063 -0.510058  negative
2 -0.239048  0.406690  0.142977  negative
3  0.294284  0.779050  0.284340  positive
4 -0.871038 -0.202532 -0.007785  negative
Пример
# Группировка с множественными агрегациями 
df_group = pd.DataFrame({
    'category': ['A','A','B','B','A'],
    'value1': [10,20,30,40,50],
    'value2': [1,2,3,4,5]
})
agg_funcs = {'value1': ['sum','mean'], 'value2': 'max'}
result = df_group.groupby('category').agg(agg_funcs)
print(result)
      value1        value2
         sum mean    max
category                  
A           80 26.67     5
B           70 35.00     4
Пример
# Работа с временными рядами: создание и скользящее среднее
dates = pd.date_range('2024-01-01', periods=10, freq='D')
ts = pd.Series(np.random.randn(10), index=dates)
rolling_mean = ts.rolling(window=3).mean()
print('Скользящее среднее с окном 3:')
print(pd.concat([ts.rename('original'), rolling_mean.rename('rolling')], axis=1).head(7))
Скользящее среднее с окном 3:
            original   rolling
2024-01-01  0.496714       NaN
2024-01-02  0.861736       NaN
2024-01-03  0.028766  0.462405
2024-01-04 -0.398063  0.164146
2024-01-05  0.406690  0.012464
2024-01-06 -0.871038 -0.287470
2024-01-07 -0.398063 -0.287470
Пример
# Сводная таблица с многомерной группировкой
np.random.seed(0)
df_pivot = pd.DataFrame({
    'Year': [2020,2020,2021,2021,2020],
    'Quarter': ['Q1','Q2','Q1','Q2','Q1'],
    'Product': ['A','A','B','B','B'],
    'Sales': np.random.randint(100,500,5)
})
pivot = pd.pivot_table(df_pivot, values='Sales', index='Year', columns='Quarter', aggfunc='sum', fill_value=0, margins=True)
print(pivot)
Quarter    Q1   Q2  All
Year                   
2020      326  473  799
2021      218  243  461
All       544  716 1260
Пример
# Использование apply с пользовательской функцией на оси
df_apply = pd.DataFrame({'x': [1,2,3], 'y': [4,5,6]})
df_apply['z'] = df_apply.apply(lambda row: row['x']**2 + row['y']**2, axis=1)
print(df_apply)
   x  y   z
0  1  4  17
1  2  5  29
2  3  6  45
Пример
# Векторизованное умножение матриц через NumPy
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
C = np.dot(A, B)   # или A @ B
print('Произведение матриц:')
print(C)
Произведение матриц:
[[19 22]
 [43 50]]
Пример
# Обработка пропущенных значений с использованием интерполяции
df_nan = pd.DataFrame({'A': [1, np.nan, 3, np.nan, 5]})
df_nan['A_interp'] = df_nan['A'].interpolate(method='linear')
print(df_nan)
     A  A_interp
0  1.0      1.0
1  NaN      2.0
2  3.0      3.0
3  NaN      4.0
4  5.0      5.0

NumPy и Pandas в Python - comments

En
Python numpy pandas (python)