Эффективная работа с большими данными в Python средствами Pandas и NumPy

Раздел: Работа с данными -> Pandas и NumPy

Основные подходы к обработке больших данных

Как сократить потребление памяти при загрузке большого датафрейма?

Самое действенное решение – использование типов данных с меньшим объёмом и чтение данных чанками. Pandas позволяет при read_csv() задать параметр dtype для каждого столбца, а также chunksize для обработки по частям. Дополнительно можно применить pd.DataFrame.memory_usage(deep=True) для анализа.

import pandas as pd

# Чтение с явным указанием типов
chunk_iter = pd.read_csv('big_dataset.csv',
                         dtype={'user_id': 'int32',
                                'value': 'float32',
                                'category': 'category'},
                         chunksize=10000)

# Обработка чанков
for chunk in chunk_iter:
    # вычисления
    pass

Python для анализа данных (python для анализа данных)

Проблема: Если тип не совпадает с реальными данными, возможна потеря точности или ошибка. Например, 'int32' не вмещает числа больше 2^31. Решение – предварительный анализ диапазонов значений через describe() или min()/max().

Типичная ошибка: Загрузка всего файла в память без явного указания типов ведёт к использованию объектов Python (строки) вместо категорий – расход памяти увеличивается в 10–20 раз.

Как обрабатывать данные, которые не помещаются в оперативную память?

Вариант – использовать библиотеку Dask, которая имитирует Pandas API, но выполняет вычисления лениво и распределённо. Однако в рамках чистого Pandas/NumPy можно применить pd.HDFStore или numpy.memmap для работы с данными на диске.

import numpy as np

# Создание memmap-файла
shape = (10_000_000, 50)
fp = np.memmap('data.bin', dtype='float32', mode='w+', shape=shape)
fp[:] = np.random.randn(*shape)  # запись

# Доступ как к обычному массиву
del fp
data = np.memmap('data.bin', dtype='float32', mode='r', shape=shape)
print(data[:5, :3])  # чтение первых пяти строк

анализ больших данных python (анализ больших данных в python)

Проблема: memmap не поддерживает все операции NumPy (например, np.linalg) без копирования в оперативную память. Решение – выполнять вычисления по частям.

Ошибка: Некорректный режим доступа ('r' вместо 'r+') при попытке записи вызывает исключение PermissionError.

Как ускорить вычисления на больших массивах NumPy?

Векторизация вместо циклов. NumPy использует оптимизированные C-функции, но если массив не помещается в кэш, скорость падает. Решение – разбивать массив на блоки (blockwise операции) или использовать np.einsum для сложных свёрток.

import numpy as np

# Матричное умножение больших матриц через блоки
A = np.random.randn(10_000, 10_000)
B = np.random.randn(10_000, 10_000)
block_size = 1000
C = np.zeros((10_000, 10_000))
for i in range(0, 10_000, block_size):
    for j in range(0, 10_000, block_size):
        for k in range(0, 10_000, block_size):
            C[i:i+block_size, j:j+block_size] += A[i:i+block_size, k:k+block_size] @ B[k:k+block_size, j:j+block_size]

Проблема: Блочное умножение требует правильного выбора размера блока – слишком маленькие блоки увеличивают накладные расходы, слишком большие вызывают промахи кэша. Рекомендуется размер, кратный 64 (размер строки кэша).

- Python анализ данных и машинное обучение (анализ данных и машинное обучение на python)
- анализ данных с использованием python (анализ данных с использованием python)
- Python анализ текстовых данных (анализ текстовых данных в python)

Дополнительные расширенные примеры

Пример 1. Чтение CSV с автоматическим приведением типов и контролем ошибок.

Пример
import pandas as pd

def read_chunked(filename, chunksize=50000):
    """Генератор с оптимизацией типов"""
    dtype_mapping = {
        'col_int': 'int16',
        'col_float': 'float32',
        'col_str': 'category'
    }
    for chunk in pd.read_csv(filename, dtype=dtype_mapping,
                             chunksize=chunksize,
                             low_memory=False,
                             parse_dates=['date_col']):
        # Уменьшение потребления памяти через преобразование
        chunk['new_feature'] = chunk['col_float'].mul(2).astype('float32')
        yield chunk

for df in read_chunked('large.csv'):
    print(df.memory_usage(deep=True).sum())
Результат: вывод размера памяти каждого чанка в байтах; обычно в 2–3 раза меньше, чем при загрузке без явных типов.

Пример 2. Использование категориальных данных для столбцов с повторяющимися значениями.

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

# Генерация синтетического датасета
n = 1_000_000
df = pd.DataFrame({
    'user_id': np.random.randint(1, 100000, n),
    'location': np.random.choice(['Moscow','SPb','Novosibirsk','others'], n),
    'value': np.random.randn(n)
})
print('До:', df.memory_usage(deep=True))
df['location'] = df['location'].astype('category')
print('После:', df.memory_usage(deep=True))
До: 32000000 bytes (для location как object)
После: 1000000 bytes (категория хранит целые индексы)

Пример 3. Параллельная обработка чанков с помощью multiprocessing.

Пример
import pandas as pd
from multiprocessing import Pool

def process_chunk(chunk):
    # Группировка и агрегация
    return chunk.groupby('category')['value'].sum()

if __name__ == '__main__':
    chunks = pd.read_csv('data.csv', chunksize=10000)
    with Pool(4) as pool:
        results = pool.map(process_chunk, chunks)
    final = pd.concat(results).groupby(level=0).sum()
    print(final.head())
Результат: агрегированные суммы по категориям, полученные с ускорением в ~4 раза на многоядерном процессоре.

Пример 4. Использование numpy.memmap для работы с многомерными массивами, не влезающими в память.

Пример
import numpy as np

shape = (20_000, 20_000)  # 3.2 ГБ для float64
# Создание файла подкачки
mm = np.memmap('large_array.bin', dtype='float64', mode='w+', shape=shape)
# Заполнение случайными данными
for i in range(shape[0]):
    mm[i] = np.random.randn(shape[1])
# Вычисление среднего по столбцам
mean_col = np.mean(mm, axis=0, dtype='float64')
print(mean_col[:5])
[ 0.001234  -0.003456  0.008901  0.000123 -0.005678]

Примечание: при таком подходе операции выполняются с подкачкой с диска, поэтому скорость ниже, но экономится оперативная память.

Большие данные в Python - comments

En
большие данные python (python)