Python

Данные, с которыми вы работаете, уже настолько большие, что вы часами ждёте их загрузки? Пора осваивать новый инструмент, который избавит вас от долгого ожидания —datatable!

“В период до 2003 года в мире было создано пять эксабайтов информации. Сейчас же каждые два дня появляются новые пять эксабайтов”, — Эрик Шмидт

Если вы пользовались языком R, то, скорее всего, вы уже работали с пакетом data.table. В R это расширение пакета data.frame. Для пользователей R он полезен в обработке больших объёмов данных (например, около 100 ГБ в RAM).

data.table в R — многофункциональный пакет с высокой производительностью. Он лёгок в использовании, удобен и быстр. Конечно, он очень известен: у него более 400 тысяч скачиваний каждый месяц и его используют почти 650 пакетов CRAN и Bioconductor.

А что делать тем, кто использует Python? Хорошие новости: для этого языка существует библиотека datatable, которая поддерживает большие данные, датасеты как внутри динамической памяти, так и вне, мультипотоковые алгоритмы и обеспечивает высокую производительность.

datatable

Современные программы с использованием машинного обучения должны уметь обрабатывать огромное количество данных и создавать несколько признаков. Это нужно для создания моделей с высокой точностью. Модуль datatable был создан как раз для этого. Он поддерживает данные размером до 100 ГБ на одном вычислительном узле на максимальной скорости вычислений. Разработка библиотеки спонсировалась H2O.ai и впервые использовалась в Driverless.ai.

В некоторой степени библиотека похожа на pandas с тем лишь отличием, что она больше сфокусирована на данных больших размеров и скорости вычислений. К тому же datatable помогает пользователю понятными сообщениями об ошибках. Сейчас вы и сами увидите, в чём эта библиотека превосходит pandas.

Установка

На MacOS установка производится при помощи pip:

pip install datatable

На Linux — при помощи бинарного пакета:

# Если у вас Python 3.5
pip install https://s3.amazonaws.com/h2o-release/datatable/stable/datatable-0.8.0/datatable-0.8.0-cp35-cp35m-linux_x86_64.whl
# Если у вас Python 3.6
pip install https://s3.amazonaws.com/h2o-release/datatable/stable/datatable-0.8.0/datatable-0.8.0-cp36-cp36m-linux_x86_64.whl

К сожалению, пока библиотека не работает на Windows, но ведётся работа для создания поддержки и этой ОС.

Для более подробной инструкции обращайтесь к документации.

Код, использованный в этой статье, можно найти на Github.

Считывание данных

Датасет —  Lending Club Loan Data — взят с Kaggle. Он содержит информацию обо всех займах в период с 2007 по 2015 год: статус займа (текущий, выплачен в срок, выплачен позже срока) и информацию об оплате. Файл состоит из 2,26 миллионов строк и 145 столбцов. Размер датасета идеален для демонстрации возможностей библиотеки.

# Импортируем библиотеки
import numpy as np
import pandas as pd
import datatable as dt

Загрузим данные в объект Frame. Это фундаментальная единица анализа в библиотеке datatable — почти то же самое, что и pandas dataframe или таблица SQL: данные содержатся в форме двумерного массива.

datatable

%%time
datatable_df = dt.fread("data.csv")
____________________________________________________________________
CPU times: user 30 s, sys: 3.39 s, total: 33.4 s                                
Wall time: 23.6 s

Функция fread() одновременно и мощная, и быстрая. Она может автоматически распознавать и считывать большинство текстовых форматов, загружать данные из .zip архивов или ссылок, считывать файлы Excel.

К тому же парсер datatable:

  • автоматически распознаёт сепараторы, заголовки, типы столбцов и тому подобное;
  • может считывать данные из многих ресурсов: файлов, ссылок, текстов, архивов, программных оболочек и масок;
  • позволяет проводить многопоточное чтение файла;
  • показывает полосу загрузки больших файлов;
  • считывает как RFC4180-совместимые, так и несовместимые файлы.

pandas

Теперь посмотрим на то, как с задачей загрузки справляется pandas.

%%time
pandas_df= pd.read_csv("data.csv")
___________________________________________________________
CPU times: user 47.5 s, sys: 12.1 s, total: 59.6 s
Wall time: 1min 4s

Результаты показывают, что datatable работает гораздо быстрее: считывание заняло меньше минуты.

Преобразование объекта Frame

Существующий объект Frame можно преобразовать в массив numpy или pandas dataframe:

numpy_df = datatable_df.to_numpy()
pandas_df = datatable_df.to_pandas()

Давайте преобразуем наши данные в объект pandas dataframe и сравним время со считыванием в pandas.

%%time
datatable_pandas = datatable_df.to_pandas()
___________________________________________________________________
CPU times: user 17.1 s, sys: 4 s, total: 21.1 s
Wall time: 21.4 s

Получается, что для работы с объектом pandas dataframe гораздо эффективнее считать данные при помощи datatable, а затем преобразовать их в pandas dataframe.

type(datatable_pandas)
___________________________________________________________________
pandas.core.frame.DataFrame

Свойства Frame

Давайте рассмотрим основные свойства этого класса. Кстати, они схожи со свойствами pandas dataframe.

print(datatable_df.shape)       # (строки, столбцы)
print(datatable_df.names[:5])   # названия первых пяти столбцов
print(datatable_df.stypes[:5])  # типы первых пяти столбцов
______________________________________________________________
(2260668, 145)
('id', 'member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv')
(stype.bool8, stype.bool8, stype.int32, stype.int32, stype.float64)

Также можно использовать команду head для того, чтобы вывести несколько первых строк датасета:

datatable_df.head(10)
Первые 10 строк датасета

Цвет показывает тип данных: красный — строки, зелёный — целые числа, синий — числа с плавающей точкой.

Сводная статистика

В pandas подсчёт сводной статистики — достаточно ресурсозатратный процесс. С datatable же всё гораздо удобнее. Для каждого столбца можно вычислить следующие значения:

datatable_df.sum()      datatable_df.nunique()
datatable_df.sd() datatable_df.max()
datatable_df.mode() datatable_df.min()
datatable_df.nmodal() datatable_df.mean()

Давайте вычислим среднее значение столбцов, используя эти две библиотеки.

datatable

%%time
datatable_df.mean()
_______________________________________________________________
CPU times: user 5.11 s, sys: 51.8 ms, total: 5.16 s
Wall time: 1.43 s

pandas

pandas_df.mean()
__________________________________________________________________
Throws memory error.

Как видим, для такого размера данных с pandas это сделать невозможно, так как происходит ошибка памяти.

Обработка данных

datatable — столбчатая структура данных, как и dataframe. Все обращения происходят при помощи квадратных скобок, как и в обычных матрицах, но с большим функционалом.

Такая же нотация DT[i, j] используется в математике при работе с матрицами, в C/C++, R, pandasи numpy. Давайте посмотрим, что мы можем делать с данными в datatable.

Выбор подмножества строк/столбцов

Нижеприведённый код выбирает весь столбецfunded_amnt датасета.

datatable_df[:,'funded_amnt']

А вот так мы можем выбрать первые пять строк и три столбца:

datatable_df[:5,:3]

Сортировка датасета

Отсортируем его по значению funded_amnt_inv при помощи обеих библиотек и сравним время работы.

datatable

%%time
datatable_df.sort('funded_amnt_inv')
_________________________________________________________________
CPU times: user 534 ms, sys: 67.9 ms, total: 602 ms
Wall time: 179 ms

pandas

%%time
pandas_df.sort_values(by = 'funded_amnt_inv')
___________________________________________________________________
CPU times: user 8.76 s, sys: 2.87 s, total: 11.6 s
Wall time: 12.4 s

И вновь мы видим преимущество datatable.

Удаление строк/столбцов

Вот так можно удалить столбец с названием member_id:

del datatable_df[:, 'member_id']

Группирование

Как и pandas, datatable поддерживает функцию groupby. Давайте найдём среднее значение столбца funded_amount, сгруппированного по значению grade.

datatable

%%time
for i in range(100):
datatable_df[:, dt.sum(dt.f.funded_amnt), dt.by(dt.f.grade)]
____________________________________________________________________
CPU times: user 6.41 s, sys: 1.34 s, total: 7.76 s
Wall time: 2.42 s

pandas

%%time
for i in range(100):
pandas_df.groupby("grade")["funded_amnt"].sum()
____________________________________________________________________
CPU times: user 12.9 s, sys: 859 ms, total: 13.7 s
Wall time: 13.9 s

Что такое .f?

f это frame proxy, который позволяет нам обращаться к объекту Frame. То есть в нашем примере dt.f — это то же самое, что и datatable_df.

Фильтрация строк

Синтаксис похож на groupby. Давайте выберем только те строки loan_amnt, для которых значения loan_amntбольше, чем funded_amnt.

datatable_df[dt.f.loan_amnt>dt.f.funded_amnt,"loan_amnt"]

Сохранение

Содержимое объекта Frame можно записать в файл csv для дальнейшего использования.

datatable_df.to_csv('output.csv')

Если у вас есть вопросы по использованию библиотеки, то обращайтесь к документации.

Заключение

Модуль datatable определённо ускоряет работу с данными по сравнению с pandas, что очень полезно при работе с большими датасетами. С другой стороны, библиотека проигрывает pandas в функциональности. Но работа над библиотекой до сих пор ведётся, поэтому в будущем надеемся на расширение функционала.

Ссылки


Перевод статьи Parul Pandey: An Overview of Python’s Datatable package