Подписка на блог

Customize in /user/extras/subscribe-sheet.tmpl.php.

Sample text.

Twitter, Facebook, VK icon VK, Telegram, LinkedIn, Odnoklassniki, Pinterest, РСС JSON Feed

Sample text.

Создание простых сводных таблиц в pandas с помощью sidetable

Крис Моффит, редактор сайта об автоматизации бизнес-задач на Python, разработал модуль sidetable.

Со слов автора новый модуль расширяет возможности value_counts() и использует API pandas для регистрации собственных методов.

Давайте разбираться, как он работает.

Для начала установим модуль:

pip3 install sidetable

Рассмотрим пример с грантами для школ США, если кратко: Конгресс еще при Обаме выделил 4 миллиарда у.е. для реформы образования, для получения гранта школе надо выбрать одну из моделей реформирования («Model Selected»).

Кстати, блокнот с исходным текстом лежит в Google Co.

Начинаем, как обычно, с импорта модулей:

import pandas as pd
import sidetable 

df = pd.read_csv('https://github.com/chris1610/pbpython/blob/master/data/school_transform.csv?raw=True', index_col=0)
df.head()

В результате импорта модуля sidetable появился новый метод stb.
Вызов stb.freq() позволяет построить сводную таблицу частот по штатам:

df.stb.freq(['State'])

Этот пример показывает, что CA (California) встречается 92 раза и составляет 12,15% от общего количества школ. Если включить в подсчеты FL (Florida), то будет 163 школы, что составляет 21,5% от общего числа школ, участвующих в грантах.

Можно сравнить этот результат с выводом стандартного метода value_counts() . При установке normalize в True возвращаемый объект будет содержать относительные частоты уникальных значений:

df['State'].value_counts(normalize=True)

Хм... разница заметна, даже невооруженным глазом.

Можно составить список штатов, которые составляют около 50% от общего числа с помощью аргумента thresh (рус. «молотить») и сгруппировать все остальные штаты в категорию «Others»:

df.stb.freq(['State'], thresh=.5)

Теперь видим, что 8 штатов составляют практически 50% от общего количества.
Можем для симпатичности переименовать категорию «Others», используя ключевой аргумент other_label:

df.stb.freq(['State'], thresh=.5, other_label='Остальные штаты')

sidetable позволяет группировать столбцы для лучшего понимания распределения. Посмотрим, как различные «Модели трансформации» применяются в разных регионах?

df.stb.freq(['Region', 'Model Selected'])

sidetable позволяет передавать значение value, по которому можно суммировать (вместо подсчета вхождений).

df.stb.freq(['Region'], value='Award_Amount')

Узнали, что Northeast (Северо-Восток) затратил наименьшее количество средств на реформу, а 37% от общих расходов было потрачено на школы в South (Южном) регионе.

Посмотрим на типы выбранных моделей и определим разбиение 80/20 для выделенных средств:

df.stb.freq(['Region', 'Model Selected'],
             value='Award_Amount', thresh=.82,
             other_label='Remaining')

Это аналог crosstab в Pandas:

Можно улучшить читабельность данных в pandas за счет добавления форматирования столбцов Percentage и Amount. Укажем для этого ключевой аргумент style=True:

df.stb.freq(['Region'], value='Award_Amount', style=True)

Пример построения таблицы пропущенных значений:

df.stb.missing()

Видим 10 пропущенных значений в столбце Region, что составляет чуть менее 1,3% от общего значения в этом столбце.

Похожий результат можно получить с помощью info() :

Ссылка на остальную документацию для модуля sidetable.

Для визуализации пропущенных значений см. модуль missingno.

Создание собственных методов в pandas

В качестве примера можно взять исходный текст модуля sidetable здесь.

В верхней части файла импортируется pandas, чтобы получить доступ к декоратору:

import pandas as pd

@pd.api.extensions.register_dataframe_accessor("stb")
class SideTableAccessor:
    def __init__(self, pandas_obj):
        self._validate(pandas_obj)
        self._obj = pandas_obj

Эта часть кода создает класс метода и определяет значение метода (stb). В момент импорта модуля, содержащего данный код, метод stb станет доступен для всех фреймов данных.

Когда создается экземпляр класса, текущий DataFrame будет проверен с помощью метода _validate() и затем будет доступен через self._obj.

@staticmethod
def _validate(obj):
    # verify this is a DataFrame
    if not isinstance(obj, pd.DataFrame):
        raise AttributeError("Must be a pandas DataFrame")

Вся работа выполняется в методах freq и missing. Необходимо убедиться, что вернулся правильный DataFrame.

Полная версия метода missing:

def missing(self, clip_0=False, style=False):
    """ Build table of missing data in each column.

        clip_0 (bool):     In cases where 0 counts are generated, remove them from the list
        style (bool):     Apply a pandas style to format percentages

    Returns:
        DataFrame with each Column including total Missing Values, Percent Missing
        and Total rows
    """
    missing = pd.concat([self._obj.isna().sum(),
                         self._obj.isna().mean()],
                        axis='columns').rename(columns={
                            0: 'Missing',
                            1: 'Percent'
                        })
    missing['Total'] = len(self._obj)
    if clip_0:
        missing = missing[missing['Missing'] > 0]

    results = missing[['Missing', 'Total',
                       'Percent']].sort_values(by=['Missing'],
                                               ascending=False)
    if style:
        format_dict = {'Percent': '{:.2%}', 'Total': '{0:,.0f}'}
        return results.style.format(format_dict)
    else:
        return results

Спасибо, Крис!

Ссылка на оригинал статьи.

Подписаться на блог
Поделиться
Отправить
Запинить
Популярное