Рубрики
Без рубрики

Упростите данные биндин с пользовательским диктором

В науке данных часто нужно объединить непрерывные данные, чтобы обобщать шумные наблюдения. Его … помеченный Python, Datascity.

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

Особенности того, как одна группа эти банки могут варьироваться. Для случаев, когда вы просто используете центральные значения, чтобы быть потокарными/напольными, я придумал элегантное и перспективное решение с использованием модели данных контейнеров Python.

Контейнеры – это объекты, которые хранят вещи и используют квадратные скобки [] Обозначение для доступа:

  • Элементы списка my_list можно получить доступ и модифицировать через индекс Я с my_list [я] утверждение.
  • Значения словаря my_dict Доступ к доступу и доступен и mofied через ключ к с my_dict [k] утверждение. Я создал пользовательский тип контейнера Bins в абстрактные банкины данных. Элементы банки данных my_bins Доступ к доступу и модифицировано через любой Настоящее число n с my_bins [n] Отказ Если n не является фактическим ключом my_bins Затем он будет округлен до ближайшего фактического ключа.

Bins инициализируется с нужными интервалами. Каждый интервал по существу является ключом, соединенным с количеством, где количество начинается в 0.

>>> bins = Bins([-6, -3, 0, 3, 6])
>>> bins
{-6: 0, -3: 0, 0: 0, 3: 0, 6: 0}
>>> bins[3] += 1                    # n = 3
>>> bins
{-6: 0, -3: 0, 0: 0, 3: 1, 6: 0}
>>> bins[7] += 1                    # n = 6
>>> bins[11] += 1                   # n = 6
>>> bins[6.5] += 1                  # n = 6
>>> bins
{-6: 0, -3: 0, 0: 0, 3: 1, 6: 3}
>>> bins[-1000000] += 1             # n = -6
>>> bins
{-6: 1, -3: 0, 0: 0, 3: 1, 6: 3}
>>> bins[0.5] += 1                  # n = 0
>>> bins
{-6: 1, -3: 0, 0: 1, 3: 1, 6: 3}

Как вы можете видеть, это чувствует себя ужасно, как словарь-инфакт, Bins наследует абстрактный базовый класс Mutablappapping Чтобы отразить интерфейс, который можно ожидать от Дикт Отказ Минимальный подкласс потребует переопределения следующих методов.

class Bins(MutableMapping):
    def __init__(self, *args, **kwargs):
        ...

    def __getitem__(self, key):
        ...

    def __setitem__(self, key, value):
        ...

    def __delitem__(self, key):
        ...

    def __iter__(self):
        ...

    def __len__(self):
        ...

Сначала мы хотим инициализировать Bins с нужными интервалами. Мы можем сохранить это как во внутреннем диктоме, который будет держать содержимое Bins Отказ

    def __init__(self, intervals):
        empty_bins = {interval: 0 for interval in intervals}
        self._dict = empty_bins

__GetItem __ () и __setitem __ () Методы определяют поведение использования квадратных кронштейнов [] Обозначение. Мы хотим пересекать ключ И закруглить его до ближайшего интервала, перед применением допустимого ключа (интервал) на наш внутренний словарь.

    def __getitem__(self, key):
        interval = self._roundkey(key)
        return self._dict[interval]

    def __setitem__(self, key, value):
        interval = self._roundkey(key)
        self._dict[interval] = value

    def _roundkey(self, key):
        intervals = list(self._dict.keys())
        minkey = intervals[0]
        midkeys = intervals[1:-1]
        maxkey = intervals[-1]

        if key <= minkey:
            return minkey
        elif key >= maxkey:
            return maxkey
        elif key in midkeys:
            return key
        else:
            i = bisect_left(intervals, key)
            leftkey = intervals[i - 1]
            rightkey = intervals[i]

            if abs(leftkey - key) < abs(rightkey - key):
                return leftkey
            else:
                return rightkey

Как видите, метод _roundkey () раунды ключ к ближайшему интервалу. Мы проверяем ли ключ Первый промежуток времени, прежде чем использовать Python’s bisect_left Чтобы найти интервалы потока и полов относительно ключ и вернуть ближайший.

И что нам нужно сделать, чтобы добывать нефтяные операторы, такие как + = работающий? Ничего! Все, что они делают, это получение значения из прошедшего ключа через __GetItem __ () , применяя операцию для значения, и присвоение нового значения ключению через __setitem __ () Отказ

Так что, если у вас тоже есть __delitem __ () , __iter __ () и __лен __ () напрямую интерфейс с Self._dict. у тебя будет работать Bins вашего собственного!

Производственная готовность

Но я не совсем доволен этим. В первую очередь, если мы пройдем интервалы, которые не являются заказа, то мы полностью привернули, как _roundkey () Работает в нахождении ближайшего интервала. Мы может Просто сортируйте интервалы сами по инициализации.

    def __init__(self, intervals):
        empty_bins = {interval: 0 for interval in sorted(intervals)}
        self._dict = empty_bins

Перед Python 3.7 это не будет идеально, поскольку словари не гарантируют заказа ввода. Однако они делают, однако мы все еще можем оказаться неупорядоченным Self._dict. Если кто-то использовал Обновление () метод. Я не могу предшествовать ситуации, которую кто-то захочет сделать это, но Обновление () Используется в сериализации данных и в любого выставленности Mutablappapping Так что это хорошая идея, чтобы обновить наш внутренний порядок словаря.

К счастью, у нас есть Сортируется от SortedContainers Пакет Который будет Гунтинте на ключах словаря всегда будут отсортированы.

    def __init__(self, intervals):
        empty_bins = {interval: 0 for interval in intervals}
        self._sdict = SortedDict(empty_bins)

Мы также можем кэшировать _roundkey () результат часто пропущенных ключей. Я нашел в некоторых ситуациях, которые я использовал Bins В алгоритме это могло значительно улучшить производительность, как округление плавать -тип ключ к интервалу немного дорого, но точно такой же ключ пропускается регулярно.

Питона @lru_cache () Декоратор делает это просто для реализации. Вы можете просто попнуть его на функцию с помощью hashable аргументов, и это будет использовать LRU кэш хранить результаты частое функции вызовы

Поскольку акт ключей округления заинтересован только в Интервалы Bins Я создал метод UTIL (экземпляр-агностик), который принимает только интервалы и переданный ключ, чтобы найти ближайший интервал и удобно завернуть _roundkey () Отказ

class Bins(MutableMapping):
    ...
    @property
    def intervals(self):
        return tuple(self._sdict.keys())

    def _roundkey(self, key):
        return find_closest_interval(self.intervals, key)
    ...

@lru_cache() def find_closest_interval(intervals, key):
    minkey = intervals[0]
    midkeys = intervals[1:-1]
    maxkey = intervals[-1]

    if key <= minkey:
        return minkey
    elif key >= maxkey:
        return maxkey
    elif key in midkeys:
        return key
    else:
        i = bisect_left(intervals, key)
        leftkey = intervals[i - 1]
        rightkey = intervals[i]

        if abs(leftkey - key) < abs(rightkey - key):
            return leftkey
        else:
            return rightkey

Плавник

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

Я выставил Bins Реализация, которую я использовал в моей библиотеке тестирования случайности Coinflip , доступно в Coinflip.Collions. Bins пространство имен. Я верю, что это готово к производству, но, возможно, есть причуды, которые я еще предстоит столкнуться и тестировать! Исходный код доступен на Github ( Испытания тоже).

Действительно прохладный проект будет реализовывать интервальные диапазоны, чтобы биннинг не должен положиться на «центральные значения». Это может быть достигнуто очень хорошо с Ломтики (например obj [a: b: c] синтаксис) – это не беспрецедентно, как Пандас Использует ломтики для выражения операций довольно красиво.

Для любых любителей Raymond Hettinger вы узнаете, что каждый трюк и инструмент, который я использую здесь, был сильно под влиянием него. Спасибо также redditore levenphonons для того, чтобы дать мне большие отзывы!

Оригинал: “https://dev.to/honno/simplify-data-binning-with-a-custom-dict-28i5”