Статьи
December 5, 2022

Всё о методе shift() в pandas

Предположим, вы столкнулись с ситуацией, когда вам нужно сдвинуть все строки в датафрейме или вы хотите вычислить разницу в последовательных рядах. Метод Pandas shift() вам в помощь.

Затронем пару теоретических и пару практических моментов:

Сдвиг значений с помощью periods

Метод shift() сдвигает индексы в датафрейме на нужное количество значений. Простейший вызов этой функции должен содержать аргумент periods (по умолчанию periods=1), который представляет собой количество шагов сдвига для нужной оси. По умолчанию сдвигаются значения по вертикали вдоль оси 0. Отсутствующие значения, появившихся в результате сдвига, будут автоматически заполнены NaN.

Давайте посмотрим, как это работает, на примере. Создадим датафрейм:

df = pd.DataFrame({
 "A": [1, 2, 3, 4, 5],
 "B": [10, 20, 30, 40, 50]
})

Сдвинем индекс на 1 строку по вертикали:

df.shift(periods=1)
# Так тоже можно:
df.shift(1)

Для замены NaN можно использовать аргумент fill_value и проставить вместо пропусков 0:

df.shift(periods=1, fill_value=0)

Кроме того, в periods можно передавать отрицательные числа, чтобы сдвигать значения в противоположном направлении.

Чтобы сдвинуть значения по горизонтали, можно задать axis=1:

df.shift(periods=1, axis=1)

Сдвиг данных временного ряда с помощью freq

У метода shift() также есть аргумент freq. он позволяет выполнять сдвиг на основе некоей заданной частоты, что полезно при работе с данными временных рядов.

Чтобы использовать аргумент freq, необходимо убедиться, что индексами в вашем датафрейме являются типы date или datetime, иначе возникнет ошибка NotImplementedError.

Давайте посмотрим, как это работает, на примере:

df = pd.DataFrame({
 "A": [1, 2, 3, 4, 5],
 "B": [10, 20, 30, 40, 50]
 }, 
 index=pd.date_range("2020-01-01", freq="D", periods=5)
)

Сдвинем индекс на 10 дней.

df.shift(freq='10D')

# эквивиалент:
df.shift(periods=10, freq="D")

При выполнении той же операции с помощью только одного аргумента periods вы получите следующий результат. Конечно, это не то, чего мы хотим.

Вычисление разницы в последовательных рядах

Предположим, вам нужно использовать значение предыдущего ряда для расчёта чего-либо. Тут тоже пригодится метод shift():

df = pd.DataFrame({
 "date": pd.date_range("2020-01-01", freq="D", periods=5),
 "sales": [22, 30, 32, 25, 42]
})

Рассчитаем изменение продаж в последовательных рядах.

df["diff"] = df["sales"] - df.shift(1)["sales"]

Короче, эта функция крайне полезна при работе с временными рядами. Давайте рассмотрим еще один практический пример.

Вычисление разницы для временного ряда

Теперь предположим, что вас попросили рассчитать изменение продаж за 7 дней следующим образом:

value_1 = Day_8 - Day_1
value_2 = Day_9 - Day_2
value_3 = Day_10 - Day_3
...
value_n = Day_N - Day_N-7

Использование метода shift() с аргументом freq — идеальный способ решения этой задачи. Давайте воспользуемся методом read_csv() (пример данных здесь) с аргументами parse_dates и index_col для формирования датафрейма.

df = pd.read_csv(
 "https://raw.githubusercontent.com/obulygin/content/main/pandas_shift/time_series.csv", 
 parse_dates=["date"], 
 index_col=["date"],
)

Обратите внимание, что запись для "2020-01-08" отсутствует. Выполнив df.shift(freq='7D'), вы должны получить результат с записью для "2020-01-08".

Затем мы можем рассчитать изменение продаж за 7 дней:

the_7_days_diff = df["sales"] - df.shift(freq="7D")["sales"]

Обратите внимание:

  • в результате есть запись для "2020-01-08";
  • значение "2020-01-08" — NaN, потому что изначально в данных не было такого значения;
  • значения для даты с "2020-01-01" по "2020-01-07" — NaN, потому что их нет и в df.shift(freq='7D');
  • последние 6 записей — NaN, потому что в датафрейме не было этих значений.

Заключение

Метод shift() может быть очень полезен, когда нужно сдвинуть все строки в датафрейме или требуется использовать предыдущую строку для вычислений. А ещё он применяется при работе с данными временных рядов.

Рекомендуем также ознакомиться с документацией метода.

PythonTalk в Telegram

Чат PythonTalk в Telegram

Предложить материал | Поддержать канал

Источник: Medium
Перевод и адаптация: Екатерина Прохорова