Руководство по кодированию и инженерным функциям даты и времени

Пояснение: на изображении показана дата, а также на человеке надеты наручные часы, которые показывают время, отсюда и изображение!

вступление

Давайте начнем с того, что проясним некоторые вещи. Прежде всего, дата, время и дата-время не совпадают. Pandas имеет только тип даты и времени, в котором каждая ячейка является объектом pandas Timestamp. В пандах, если вы преобразуете столбец, содержащий только дату, в дату и время, то по умолчанию часть «время» будет 00:00, но вам следует избегать использования части времени по очевидным причинам. При работе со столбцами, содержащими только время, есть еще одно «следите за», скажем, 11:00 Перед ним будет стоять текущая дата!

Как видите, дата, представленная в виде строки, была преобразована в Timestamp с 00:00:00 временем, а текущая дата (дата выполнения кода) была добавлена ​​к времени одиночества.

Учитывая текущую дату, которая автоматически добавляется как часть исходных данных, это приведет к огромным проблемам.

Имея это в виду, давайте перейдем к созданию функций из них.

Разработка функций для даты, времени и переменных даты и времени

В этом разделе мы создадим несколько функций из доступных столбцов, создав GenProcessor для каждого типа данных.

Технические даты

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

Давайте начнем с определения нашего пользовательского преобразователя sklearn.

Мы создадим класс, который будет наследоваться от BaseEstimator и TransformerMixin, среди прочего, он дает нам сгенерированный метод fit_transform, который, как следует из названия, вызывает метод fit, а затем метод transform. Также отметим, что сгенерированные функции будут масштабироваться до диапазона [0,1], когда это уместно.

Некоторые константы и довольно простой метод подгонки

Логика трансформации высокого уровня

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

Мы будем следовать примерно такому же формату. Метод apply применяет переданную функцию к каждой серии нашего фрейма данных. Как упоминалось в начале, мы предполагаем, что только подмножество данных, имеющих столбцы даты (в виде строк), будет передано нашему преобразователю, в основном с использованием ColumnTransformer. После извлечения требуемого атрибута мы добавим требуемый суффикс ко всем именам столбцов. И последнее, но не менее важное, поскольку в месяце от максимума до максимума 31 день, а в году 12 месяцев, мы делим день и месяц на 31 и 12 соответственно. Мы могли бы масштабировать год, но это работа масштабатора, учитывая, что нет определенных минимальных и максимальных границ, как для дня и месяца. Реализуем оставшиеся методы.

  • Поскольку день недели находится в диапазоне от 0 до 6, для его масштабирования мы делим на 6
  • Поскольку четвертей 4, то есть от 0 до 3, для масштабирования делим на 3.
  • Так как день недели 0 представляет собой понедельник, дни недели 5 и 6 являются выходными.
    Чтобы получить 0/1 вместо False/True, мы преобразуем логический результат в целое число.

Теперь давайте обратим наше внимание на создание функций вне времени.

Инженерные времена

Как видите, мы разделим время на утро, день, вечер и ночь. Мы также будем извлекать час.

Бонус: такое преобразование не сохраняет циклический характер значений, чтобы сохранить их, вы можете использовать CyclicalTrasnformer, использующий синус и косинус.

Снова некоторые константы и очень простой метод подгонки,

Метод преобразования

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

Чтобы преобразовать наш объект time в целое число, представляющее время в двадцать четыре часа, мы используем быстрый прием умножения часа на 100, чтобы сдвинуть его на 2 десятичных знака влево и добавить к нему минуты (минуты). Как видите, вместо того, чтобы использовать and в условном выражении, мы написали его так, как сделал бы любой математик. Потому что наука о данных — ничто без математики.

Дата разработки Время

Теперь обратим внимание на дату и время. Честно говоря, благодаря защищенным методам, определенным в DateGenProcessor и TimeGenProcessor, делать особо нечего. Давайте идти!

Мы просто наследуем наши DateGenProcessor и TimeGenProcessor. Давайте реализуем метод подгонки и преобразования.

Нет ничего такого, чего бы мы не видели до сих пор.

Самоанализ: мы могли бы использовать композицию вместо наследования, попробуйте сами!

Вот весь код, связанный с разработкой функций, для справки (не забывайте, что ниже сути есть кодирование).

Ненадолго оторвитесь от экрана!

Кодирование даты, времени и переменных даты и времени

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

Даты кодирования

Мы будем представлять даты как разницу между датой, которую нужно закодировать, и самой ранней датой, присутствующей в фазе fit. При этом минимальное закодированное значение будет равно 0, следовательно, мы будем кодировать отсутствующие значения как -1.

Логика подгонки

Чтобы выполнить преобразование, а также обратное преобразование, нам понадобится минимальная дата в каждой функции.

Логика трансформации

Поскольку min_dates — это фрейм данных, мы можем напрямую вычесть его из фрейма данных, который нужно преобразовать. Нам не нужно беспокоиться о нулях при вычитании, потому что объект pd.Timestamp минус None есть не что иное, как None.
Вычитание даст нам фрейм данных, заполненный pandas.Timedelta объектами. Затем мы извлечем атрибут days, если значение не равно нулю, если да, то заполним его значением -1. Метод applymap кадра данных pandas применяет переданную функцию к каждому элементу каждой серии. Это перестановка метода apply, который применяет функцию к каждой серии фрейма данных, и метода map, который применяет функцию к каждому элементу. серии.

Логика обратного преобразования

Обратное преобразование — это не что иное, как операция обращения/отмены преобразованных данных. Поскольку мы знаем, что целые числа имеют единицу «дни», мы сначала преобразуем их в объекты pandas Timedelta и просто добавляем количество дней к сохраненным минимальным датам. Наконец, поскольку после выполнения этой операции мы получим ряд даты и времени, мы берем только часть даты.

Бонус: тестирование нашего собственного трансформатора

Давайте быстро напишем модульные тесты для нашего пользовательского преобразователя.

Подготовка тестовых данных

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

Проверка логики преобразования

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

  • Форма данных остается неизменной, поскольку мы выполняем преобразование на месте.
  • Поскольку 2-й элемент (индекс 1) в данных тестирования является самой низкой датой, он был закодирован как 0.
  • Поскольку 1-й элемент опережает минимальную дату на 2 дня, он был правильно закодирован как 2 (14 — 12)
  • Нуль был закодирован как -1

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

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

Тестирование логики обратного преобразования

Здесь мы сначала преобразуем наши исходные данные, а затем выполняем обратное преобразование преобразованных данных. А затем мы проверяем, получаем ли мы исходную дату по индексу 1, которая была закодирована (как показано выше) как 2. Давайте теперь перейдем к кодированию времени и времени, функциям даты и времени.

Время кодирования

Мы преобразуем объекты datetime.time в целое число, представляющее время в 24-часовом формате, а затем разделим его на 2359, максимально возможное целое число, представляющее 23:59. для того, чтобы масштабировать, а также. Мы выполняем масштабирование внутри кодировщика и не сохраняем его для масштабатора, поскольку существует определенная максимальная граница (2359), о которой масштабатор не знает. Хотя мы можем отслеживать этот столбец в закодированном времени и использовать его, чтобы решить, как масштабирование должно быть выполнено позже, но это выходит за рамки этой статьи, давайте не будем усложнять.

Подходящая логика

Подгонки не к чему, так как преобразование, как и обратное преобразование, не зависит от обучающих данных.

Логика преобразования и обратного преобразования

Подобно логике, используемой при генерации признаков из столбцов времени, мы сдвигаем час на два десятичных знака влево и добавляем к нему минуты, чтобы получить военное время, и, наконец, делим на 2359.
Для обратного преобразования мы обратить вспять процесс трансформации. Так как мы разделили на 2359 в качестве последнего шага, мы сначала умножаем закодированное время на 2359. Затем, чтобы получить доступ к двум крайним левым цифрам, мы делим на 100 (и берем целую часть), чтобы получить доступ к двум крайним правым цифрам, мы берем по модулю ( и взять целую часть). Мы также заботимся о нулях. Если вы находите это запутанным, взгляните на приведенный ниже фрагмент кода, который я написал при написании модульных тестов.

Кодирование Дата Время

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

Подходящая логика

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

Логика преобразования и обратного преобразования

Во время преобразования мы вычитаем фрейм данных, который нужно преобразовать, на сохраненные минимальные значения даты и времени. Теперь, поскольку в объекте pandas.Timedelta нет атрибута minute, мы делим total_seconds на 60.
Во время обратного преобразования мы просто конвертируем значение в минуты, указав unit = "m" при преобразовании целочисленного значения в объект pandas.Timedelta. Вот весь код, связанный с кодировкой для справки,

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

Знаете ли вы, что на кнопке со значком «Хлопки» разработчики также указали обратный вызов onLongPress вместе с обратным вызовом onPress? Попробуйте!

Вы можете связаться со мной на Linkedin susmit-vengurlekar или написать мне по электронной почте [email protected]. Вы можете увидеть, чем я занимаюсь, на Github susmit.py

Интересуетесь инженерией данных? Вы находитесь в правильном месте! Следите за открытыми вакансиями в Zeza Tech