Данные, с которыми вы работаете, уже настолько большие, что вы часами ждёте их загрузки? Пора осваивать новый инструмент, который избавит вас от долгого ожидания —datatable!
“В период до 2003 года в мире было создано пять эксабайтов информации. Сейчас же каждые два дня появляются новые пять эксабайтов”, — Эрик Шмидт
Если вы пользовались языком R, то, скорее всего, вы уже работали с пакетом data.table
. В R это расширение пакета data.frame
. Для пользователей R он полезен в обработке больших объёмов данных (например, около 100 ГБ в RAM).
data.table
в R — многофункциональный пакет с высокой производительностью. Он лёгок в использовании, удобен и быстр. Конечно, он очень известен: у него более 400 тысяч скачиваний каждый месяц и его используют почти 650 пакетов CRAN и Bioconductor.
А что делать тем, кто использует Python? Хорошие новости: для этого языка существует библиотека datatable
, которая поддерживает большие данные, датасеты как внутри динамической памяти, так и вне, мультипотоковые алгоритмы и обеспечивает высокую производительность.
datatable
![](https://cdn-images-1.medium.com/max/800/1*CDs0obGYV8BO5SrJWcsm4w.png)
Современные программы с использованием машинного обучения должны уметь обрабатывать огромное количество данных и создавать несколько признаков. Это нужно для создания моделей с высокой точностью. Модуль 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)
![](https://cdn-images-1.medium.com/max/800/1*64byY9K1c6TtfKhcpFLM3Q.png)
Цвет показывает тип данных: красный — строки, зелёный — целые числа, синий — числа с плавающей точкой.
Сводная статистика
В 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
. Все обращения происходят при помощи квадратных скобок, как и в обычных матрицах, но с большим функционалом.
![](https://cdn-images-1.medium.com/max/800/1*iSwJw9xPQNu90lAMtJfJCg.png)
Такая же нотация DT[i, j] используется в математике при работе с матрицами, в C/C++, R, pandas
и numpy
. Давайте посмотрим, что мы можем делать с данными в datatable
.
Выбор подмножества строк/столбцов
Нижеприведённый код выбирает весь столбецfunded_amnt
датасета.
datatable_df[:,'funded_amnt']
![](https://cdn-images-1.medium.com/max/800/1*gqtt8FPlX3jJP0Ge-sfY7w.png)
А вот так мы можем выбрать первые пять строк и три столбца:
datatable_df[:5,:3]
![](https://cdn-images-1.medium.com/max/800/1*_V71gWvQEhaRelnDe1_pRg.png)
Сортировка датасета
Отсортируем его по значению 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