Преобразование строки даты в столбец за последние N дней

Я хочу построить модель прогнозирования временных рядов, используя такие функции, как неделя года, день недели, время года и т. д.

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

Моя текущая таблица выглядит так:

    date        id  score
0   2014-01-01  A   75
1   2014-01-01  B   1
2   2014-01-01  C   2
4   2014-01-02  A   84
5   2014-01-02  B   1
6   2014-01-02  C   3
8   2014-01-03  A   1
9   2014-01-03  B   1
10  2014-01-03  C   1

Поэтому я хочу, чтобы каждая строка выглядела так:

    date        id  score  date_1 date_2 date_3 date_4 date-5
10  2014-01-03  A   1      84     75     0      0      0 
 9  2014-01-03  B   1      1      1      0      0      0

Date_1 - это оценка A, за день до даты в столбце date, date_2 - за два дня до нее и так далее ...

Чтобы я мог предсказать следующий день, используя информацию за последние 5 дней и другие функции, которые не имеют отношения к этому вопросу. Нормально заполнять значения NaN 0

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
53
2

Ответы 2

Вы можете использовать groupby(id) и shift. Перед использованием следующей команды вы должны отсортировать df по дате: df.sort_values('date'):

for i in range(5):
    df['date_'+str(i+1)] = df.groupby('id')['score'].shift(i+1).fillna(0).astype(int)

Использование приведенной выше команды дает следующий df:

Хороший ответ - см. Ниже пример смещения с использованием timedelta.

ajrwhite 19.12.2018 19:22

Это работает быстро и плавно, спасибо. Это можно будет реализовать, если я могу заполнить недостающие даты для каждого идентификатора продукта нулями. У вас есть идея сделать это?

meliksahturker 19.12.2018 22:14

Сдвиг во времени с использованием Timedelta

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

Вы можете справиться с этим, преобразовав DataFrame во временной ряд, а затем используя параметр freq в DataFrame.shift() с объектом pandas.Timedelta.

Пример данных:

import pandas as pd
df = pd.DataFrame({'date': ['2014-01-01'] * 3 +
                           ['2014-01-02'] * 3 +
                           ['2014-01-03'] * 3,
                   'id': ['A', 'B', 'C'] * 3,
                   'score': [75, 1, 2, 84, 1, 3, 1, 1, 1]})
df.date = pd.to_datetime(df.date)
df.set_index('date', inplace=True)

Идентификаторы означают, что нам нужна пара циклов, чтобы все было разделено:

for i in range(5):
    for id in df.id.unique():
        col = 'date_{}'.format(i+1)
        freq = pd.Timedelta('{}d'.format(i+1))
        df.loc[df.id==id, col] = df.loc[df.id==id, 'score'].shift(freq=freq)
    df[col] = df[col].fillna(0).astype(int)

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

Вывод:

           id  score  date_1  date_2  date_3  date_4  date_5
date                                                        
2014-01-01  A     75       0       0       0       0       0
2014-01-01  B      1       0       0       0       0       0
2014-01-01  C      2       0       0       0       0       0
2014-01-02  A     84      75       0       0       0       0
2014-01-02  B      1       1       0       0       0       0
2014-01-02  C      3       2       0       0       0       0
2014-01-03  A      1      84      75       0       0       0
2014-01-03  B      1       1       1       0       0       0
2014-01-03  C      1       3       2       0       0       0

Спасибо за обобщенный ответ, потому что да, в датах есть пробелы, и даты не нужно сортировать по индексу, так что это хорошее видение с вашей стороны. Однако, когда я запустил точный код с полной таблицей, я получил ошибку: «ValueError: не удается переиндексировать с повторяющейся оси».

meliksahturker 19.12.2018 21:36

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

ajrwhite 20.12.2018 03:10

Похоже, у вас, вероятно, есть повторяющиеся пары дата + идентификатор в вашей полной таблице (например, несколько записей для A в одну и ту же дату). Это выходит за рамки вопроса, но будет исправлено с помощью .drop_duplicates(['date', 'id']) до того, как вы включите 'date' в индекс (или вам может потребоваться сделать .groupby(['date', 'id']).score.sum(), в зависимости от причины проблемы. Вежливо попросите, чтобы вы проголосовали за и одобрили этот ответ, если это решит вашу проблему, так как я думаю, что это более безопасное решение, чем использование числовой индексации.

ajrwhite 20.12.2018 04:14

Я действительно ценю твою помощь. Я пробовал, но отбрасывал дубликаты и groupby.sum, но ничего не вышло. Ошибка все та же. Вот полный набор данных: wetransfer.com/downloads/…

meliksahturker 20.12.2018 11:44
drop_duplicates() исправляет ошибку, поскольку в вашем наборе данных дублируются пары дата / идентификатор. Я подозреваю, что вы неправильно выполнили drop_duplicates. После загрузки DataFrame запустите df.drop_duplicates(['date', 'id'], inplace=True), и тогда весь код будет работать правильно.
ajrwhite 20.12.2018 14:17

Другие вопросы по теме