DaryaDu 29 августа 2020

📊 Интерактивный биннинг в Jupyter: подбираем оптимальную ширину полос гистограммы

О том, как быстро найти оптимальную ширину полос гистограммы (бинов) с помощью интерактивной гистограммы в Jupyter Notebook или JupyterLab, позволяющей изменять ширину бинов на лету.

Исследование данных – самый важный шаг в любом Data Science проекте. Такие исследования обычно начинаются с рассмотрения того, как распределены переменные. Именно в этом прекрасно помогают гистограммы.

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

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

В этой инструкции мы покажем, как настроить оптимальную ширину полос гистограммы (бинов) с помощью интерактивной гистограммы, созданной на базе plotly и ipywidgets в Jupyter Notebook или JupyterLab.

Примечание
Ниже демонстрируется построение интерактивной гистограммы с помощью plotly, но вы можете использовать те же приемы и с другой графической библиотекой – например, seaborn или matplotlib. О преимуществах экосистемы Jupyter для Data Science мы писали в статье JupyterLab и Jupyter Notebook — мощные инструменты Data Science.

В качестве практического примера рассмотрим распределение времени полета в минутах 300 тысяч рейсов, вылетавших из Нью-Йорка в 2013 г. (датасет NYCflights13). Полный код статьи можно найти в виде Jupyter-блокнота на GitHub.

Гистограмма с интерактивным биннингом

Результат выполнения приведенного кода
Результат выполнения приведенного кода

На этом рисунке изображен конечный результат. При изменении ширины бинов с помощью ползунка график автоматически корректируется.

Чтобы реализовать это, используем комбинацию plotly.graph_objs (строит гистограмму) и ipywidgets.Floatslider. Вот код, создающий гистограмму с настраиваемой шириной бинов:

Код для создания перестраиваемой гистограммы
        import plotly.graph_objs as go
import ipywidgets as widgets

def rebinnable_interactive_histogram(series, initial_bin_width=10):
    figure_widget = go.FigureWidget(
        data=[go.Histogram(x=series, xbins={"size": initial_bin_width})]
    )

    bin_slider = widgets.FloatSlider(
        value=initial_bin_width,
        min=1,
        max=30,
        step=1,
        description="Bin width:",
        readout_format=".0f",  # отображение в виде целого числа
    )

    histogram_object = figure_widget.data[0]

    def set_bin_size(change):
        histogram_object.xbins = {"size": change["new"]}

    bin_slider.observe(set_bin_size, names="value")

    output_widget = widgets.VBox([figure_widget, bin_slider])
    return output_widget

rebinnable_interactive_histogram(df, "air_time")
    

Пройдемся по коду построчно.

Построчный разбор кода

0. Объявляем функцию

Объявление функции
        def rebinnable_interactive_histogram(series, initial_bin_width=10):
    

Наша функция принимает два аргумента: series – это pandas.Series с данными, а initial_bin_width – ширина бинов по умолчанию. В нашем случае она равна 10 минутам полета.

1. Создаем изображение

Создание изображения
            figure_widget = go.FigureWidget(
        data=[go.Histogram(x=series, xbins={"size": initial_bin_width})]
    )
    

Мы создаем новый экземпляр типа FigureWidget. Это новый “волшебный объект” plotly. Его можно отобразить в Jupyter Notebook или JupyterLab, как и обычное изображение plotly, но новый подход имеет ряд преимуществ:

  • FigureWidget можно комбинировать с ipywidgets (фактически они для этого и созданы)
  • Такими виджетами можно управлять из кода, написанного на Python.
  • Они могут отлавливать некоторые события, при срабатывании которых можно также выполнить Python-код.

FigureWidget получает атрибут data, задающий список всех трассировок (читай: визуализаций), которые мы хотим изобразить. В нашем случае это единственная гистограмма. Значения x для нашей гистограммы берутся из series. Ширина бинов устанавливается в словаре, передаваемом в параметре xbins. Если в этом словаре установить size=None, plotly выберет ширину бинов за нас.

2. Создаем ползунок

Создание ползунка
         bin_slider = widgets.FloatSlider(
        value=initial_bin_width,
        min=1,
        max=30,
        step=1,
        description="Bin width:",
        readout_format=".0f",  # display as integer
    )
    

Мы создали объект типа FloatSlider из библиотеки ipywidgets. С помощью этого ползунка мы впоследствии будем управлять гистограммой.

3. Сохраняем ссылку на гистограмму

Сохранение ссылки на гистограмму
         histogram_object = figure_widget.data[0]
    

Мы сохраняем ссылку на гистограмму, потому что хотим управлять ею на последнем шаге. Для этого мы будем менять атрибут xbins нашего объекта, к которому можно получить доступ через histogram_object.xbins.

4. Пишем и используем функцию обратного вызова (callback)

Использование обратного вызова
          def set_bin_size(change):
        histogram_object.xbins = {"size": change["new"]}

    # Вызываем set_bin_size при изменении положения ползунка
    bin_slider.observe(set_bin_size, names="value")
    

Использованный нами FloatSlider содержит своеобразную «магию». Каждый раз, когда его значение меняется (например, когда мы двигаем ползунок), он вызывает срабатывание события. Мы можем использовать это событие для обновления ширины бинов нашей гистограммы. Это делается вызовом метода ползунка observe. Мы передаем ему функцию, которую хотим вызвать (set_bin_size) и сообщаем, когда ее нужно вызывать (names="value" означает, что функция вызывается при изменении параметра ползунка value).

Каждый раз, когда позиция ползунка меняется, он будет вызывать set_bin_size. Функция set_bin_size получает информацию о позиции ползунка через аргумент change – словарь c информацией о событии, сгенерированном bin_slider. Например, change["new"] содержит информацию о новой позиции ползунка, но мы также можем получить его старую позицию через change["old"]. Кстати, аргумент не обязан называться change – вы можете назвать его как угодно.

В функции обратного вызова set_bin_size видно, что она просто использует ссылку histogram_object, чтобы обновить параметры бинов FigureWidget (например, изменить их ширину), перезаписывая xbins.

Когда мы сложим всё это вместе, у нас получится первый прототип красивой интерактивной гистограммы.

Заключение

Гистограммы – прекрасный способ начать исследование набора данных. Plotly позволяет создать мощные интерактивные визуализации, которые можно совершенствовать далее с помощью ipywidgets.

В этой статье мы показали, как plotly и ipywidgets позволяют быстро и интерактивно подобрать подходящую ширину бинов гистограммы в Jupyter Notebook или JupyterLab.

Если вам интересны анализ и визуализация данных, обратите внимание на другие наши публикации:

Источники

РУБРИКИ В СТАТЬЕ

МЕРОПРИЯТИЯ

Комментарии 0

ВАКАНСИИ

Senior Backend developer (Java)
Москва, по итогам собеседования
Senior Backend Developer (Кипр)
от 3000 EUR до 4000 EUR

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

BUG