Данные, с которыми вы работаете, уже настолько большие, что вы часами ждёте их загрузки? Пора осваивать новый инструмент, который избавит вас от долгого ожидания —datatable!
Если вы пользовались языком 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)
Цвет показывает тип данных: красный — строки, зелёный — целые числа, синий — числа с плавающей точкой.
Сводная статистика
В 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