03.12.2022

3 способа работы с большими наборами данных в Python

1 min read

Как специалист по данным, я все больше и больше сталкиваюсь с «большими данными». То, что я оскорбительно называю большими данными, соответствует наборам данных, которые, хотя и не так велики, но достаточно велики, чтобы мой компьютер изо всех сил пытался их обработать и действительно все замедлял.

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

1. Уменьшите использование памяти за счет оптимизации типов данных.
При использовании Pandas для загрузки данных из файла он автоматически определяет типы данных, если не указано иное. В большинстве случаев это будет работать нормально, но предполагаемый тип не обязательно оптимизирован. Более того, если числовой столбец содержит пропущенные значения, то предполагаемый тип автоматически будет плавающим.

Недавно я использовал этот метод для анализа, где я имел дело в основном с целочисленными типами, представляющими годы, месяцы или дни:

В этом конкретном случае указание типов данных привело к значительному сокращению используемой памяти. Обратите внимание, что в приведенном выше примере я использовал pandas type pandas.Int16Dtype, чтобы заставить столбец, содержащий отсутствующие значения, иметь тип int. Это достигается за счет использования pandas.NA вместо numpy.nan для пропущенных значений.

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

2. Разделите данные на части.
Когда данные слишком велики, чтобы поместиться в памяти, вы можете использовать параметр chunksize Pandas, чтобы разбить данные на куски вместо работы с одним большим блоком. Использование этого параметра создает объект-итератор, который можно использовать для просмотра различных фрагментов и выполнения фильтрации или анализа, как при загрузке полного набора данных.

Вот пример использования этой опции для просмотра набора данных обзоров Yelp, извлечения минимальной и максимальной даты проверки для каждого фрагмента, а затем восстановления полного промежутка времени для обзоров:

3. Воспользуйтесь ленивой оценкой
Ленивое вычисление относится к стратегии, которая откладывает вычисление выражения до тех пор, пока значение действительно не понадобится. Ленивая оценка — важная концепция (особенно используемая в функциональном программировании), и если вы хотите узнать больше о различных способах ее использования в Python, вы можете начать здесь.

Ленивое вычисление — это основа, на которой строятся фреймворки распределенных вычислений, такие как Spark или Dask. Хотя они были разработаны для работы с кластерами, вы все равно можете использовать их для обработки больших наборов данных на вашем персональном компьютере.

Основное отличие от Pandas заключается в том, что они не загружают данные непосредственно в память. Вместо этого во время команды чтения происходит сканирование данных, определение типов данных и их разбиение на разделы (пока ничего нового). Вычислительные графы для этих разделов строятся независимо и выполняются только тогда, когда это действительно необходимо (отсюда и лень).

В предыдущем посте я привел пример Pyspark для выполнения исследовательского анализа на наборе данных, большем, чем память. Dask также довольно популярен, и его нетрудно найти (для сравнения вы можете начать здесь). Синтаксис Dask имитирует Pandas, поэтому он будет выглядеть очень знакомым, однако он ограничен использованием Python, в то время как Spark также будет работать на Java или Scala.
Другие библиотеки, такие как Vaex или Modin, предлагают аналогичные возможности, но я лично ими не пользовался.