[Перевод] Ускорение разведочного анализа данных с использованием библиотеки pandas-profiling

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

Библиотека pandas предоставляет нам множество полезных инструментов для выполнения разведочного анализа данных (Exploratory Data Analysis, EDA). Но, прежде чем воспользоваться ими, обычно нужно начать с функций более общего плана, таких как df.describe (). Правда, надо отметить, что возможности, предоставляемые подобными функциями, ограничены, а начальные этапы работы с любыми наборами данных при выполнении EDA очень часто сильно похожи друг на друга.

5w2h8ckcwdq5ukaw61r5xhdvch4.jpeg

Автор материала, который мы сегодня публикуем, говорит, что он — не любитель выполнения повторяющихся действий. В результате он, в поисках средств, позволяющих быстро и эффективно выполнять разведочный анализ данных, нашёл библиотеку pandas-profiling. Результаты её работы выражаются не в виде неких отдельных показателей, а в форме довольно подробного HTML-отчёта, содержащего большую часть тех сведений об анализируемых данных, которые может понадобиться знать перед тем, как приступать к более плотной работе с ними.
Здесь будут рассмотрены особенности использования библиотеки pandas-profiling на примере набора данных Titanic.

Разведочный анализ данных средствами pandas


Я решил поэкспериментировать с pandas-profiling на наборе данных Titanic из-за того, что в нём имеются данные разных типов и из-за наличия в нём пропущенных значений. Я полагаю, что библиотека pandas-profiling особенно интересна в тех случаях, когда данные ещё не очищены и требуют дальнейшей обработки, зависящей от их особенностей. Для того чтобы успешно выполнить подобную обработку, нужно знать о том, с чего начать, и на что обратить внимание. Здесь нам и пригодятся возможности pandas-profiling.

Для начала импортируем данные и используем pandas для получения показателей описательной статистики:

# импорт необходимых пакетов
import pandas as pd
import pandas_profiling
import numpy as np

# импорт данных
df = pd.read_csv('/Users/lukas/Downloads/titanic/train.csv')

# вычисление показателей описательной статистики
df.describe()


После выполнения этого фрагмента кода получится то, что показано на следующем рисунке.

7f2aa71998447a1618eb8d307594ad16.png


Показатели описательной статистики, полученные с помощью стандартных средств pandas

Хотя тут содержится масса полезных сведений, здесь нет всего, что было бы интересно узнать об исследуемых данных. Например, можно предположить, что во фрейме данных, в структуре DataFrame, имеется 891 строка. Если это нужно проверить, то потребуется ещё одна строка кода, определяющую размер фрейма. Хотя эти вычисления и не особенно ресурсозатратны, постоянное их повторение обязательно приведёт к потерям времени, которое, вероятно, лучше будет потратить на очистку данных.

Разведочный анализ данных средствами pandas-profiling


Теперь сделаем то же самое с использованием pandas-profiling:

pandas_profiling.ProfileReport(df)


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

Первая часть отчёта будет содержать раздел Overview (Обзор), дающий основные сведения о данных (количество наблюдений, количество переменных, и так далее). Кроме того, он будет содержать список предупреждений, уведомляющий аналитика о том, на что стоит обратить особое внимание. Эти предупреждения могут послужить подсказкой о том, на чём можно сосредоточить усилия при очистке данных.

17484c7286399fc9776298fff4f1e812.png


Раздел отчёта Overview

Разведочный анализ переменных


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

323c12003055c61e634d0575e564842b.png


Сведения о числовой переменной Age

Как можно видеть из предыдущего примера, pandas-profiling даёт нам несколько полезных индикаторов, таких, как процент и количество пропущенных значений, а также показатели описательной статистики, которые мы уже видели. Так как Age — это числовая переменная, визуализация её распределения в виде гистограммы позволяет нам сделать вывод о том, что перед нами — скошенное вправо распределение.

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

fdff915c4b0fce210387ffcfeb775b9d.png


Сведения о категориальной переменной Sex

А именно, вместо нахождения среднего, минимума и максимума, библиотека pandas-profiling нашла число классов. Так как Sex — бинарная переменная, её значения представлены двумя классами.

Если вы, как и я, любите исследовать код, то вас может заинтересовать то, как именно библиотека pandas-profiling вычисляет эти показатели. Узнать об этом, учитывая то, что код библиотеки открыт и доступен на GitHub, не так уж и сложно. Так как я не большой любитель использования «чёрных ящиков» в моих проектах, я взглянул на исходный код библиотеки. Например, вот как выглядит механизм обработки числовых переменных, представленный функцией describe_numeric_1d:

def describe_numeric_1d(series, **kwargs):
    """Compute summary statistics of a numerical (`TYPE_NUM`) variable (a Series).
    Also create histograms (mini an full) of its distribution.
    Parameters
    ----------
    series : Series
        The variable to describe.
    Returns
    -------
    Series
        The description of the variable as a Series with index being stats keys.
    """
    # Format a number as a percentage. For example 0.25 will be turned to 25%.
    _percentile_format = "{:.0%}"
    stats = dict()
    stats['type'] = base.TYPE_NUM
    stats['mean'] = series.mean()
    stats['std'] = series.std()
    stats['variance'] = series.var()
    stats['min'] = series.min()
    stats['max'] = series.max()
    stats['range'] = stats['max'] - stats['min']
    # To avoid to compute it several times
    _series_no_na = series.dropna()
    for percentile in np.array([0.05, 0.25, 0.5, 0.75, 0.95]):
        # The dropna() is a workaround for https://github.com/pydata/pandas/issues/13098
        stats[_percentile_format.format(percentile)] = _series_no_na.quantile(percentile)
    stats['iqr'] = stats['75%'] - stats['25%']
    stats['kurtosis'] = series.kurt()
    stats['skewness'] = series.skew()
    stats['sum'] = series.sum()
    stats['mad'] = series.mad()
    stats['cv'] = stats['std'] / stats['mean'] if stats['mean'] else np.NaN
    stats['n_zeros'] = (len(series) - np.count_nonzero(series))
    stats['p_zeros'] = stats['n_zeros'] * 1.0 / len(series)
    # Histograms
    stats['histogram'] = histogram(series, **kwargs)
    stats['mini_histogram'] = mini_histogram(series, **kwargs)
    return pd.Series(stats, name=series.name)


Хотя этот фрагмент кода и может показаться довольно большим и сложным, на самом деле, понять его очень просто. Речь идёт о том, что в исходном коде библиотеки имеется функция, которая определяет типы переменных. Если оказалось, что библиотека встретила числовую переменную, вышеприведённая функция найдёт показатели, которые мы рассматривали. В этой функции используются стандартные операции pandas по работе с объектами типа Series, наподобие series.mean(). Результаты вычислений сохраняются в словаре stats. Гистограммы формируются с использованием адаптированной версии функции matplotlib.pyplot.hist. Адаптация направлена на то, чтобы функция могла бы работать с различными типами наборов данных.

Показатели корреляции и образец исследуемых данных


После результатов анализа переменных pandas-profiling, в разделе Correlations, выведет корреляционные матрицы Пирсона и Спирмена.

d9556fa495d7c0f0fd337cae18e512a2.png


Корреляционная матрица Пирсона

Если нужно, то можно, в той строке кода, которая запускает формирование отчёта, задать показатели пороговых значений, применяемых при расчёте корреляции. Делая это, вы можете указать то, какая сила корреляции считается важной для вашего анализа.

И наконец, в отчёте pandas-profiling, в разделе Sample, выводится, в качестве примера, фрагмент данных, взятый из начала набора данных. Такой подход может привести к неприятным неожиданностям, так как первые несколько наблюдений могут представлять собой выборку, которая не отражает особенностей всего набора данных.

d269e9d5c6d5f6cf18041a154034fcbc.png


Раздел, содержащий образец исследуемых данных

В результате я не рекомендую обращать внимание на этот последний раздел. Вместо этого лучше воспользоваться командой df.sample(5), которая, случайным образом, выберет 5 наблюдений из набора данных.

Итоги


Подводя итог вышеизложенному, можно отметить, что библиотека pandas-profiling даёт в распоряжение аналитика некоторые полезные возможности, которые придутся кстати в тех случаях, когда нужно быстро получить общее приблизительное представление о данных или передать кому-нибудь отчёт о разведывательном анализе данных. При этом настоящая работа с данными, учитывающая их особенности, выполняется, как и без использования pandas-profiling, вручную.

Если вы хотите взглянуть на то, как выглядит весь разведывательный анализ данных в одном Jupyter-блокноте — взгляните на этот мой проект, созданный с помощью nbviewer. А в этом GitHub-репозитории можно найти соответствующий код.

Уважаемые читатели! С чего вы начинаете анализ новых наборов данных?

1ba550d25e8846ce8805de564da6aa63.png

© Habrahabr.ru