Окончательное руководство по оконным функциям Python

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

Оконная функция — это популярная техника, используемая для анализа подмножества со связанными значениями. Она обычно используется в SQL, однако эти функции чрезвычайно полезны и в Python.

Если вы хотите ознакомиться с нашими материалами по оконным функциям SQL, мы также создали статью «The Ultimate Guide to SQL Window Functions» и видеоролик на YouTube!

В этой статье обсуждаются:

  • Различные типы оконных функций

  • Где/как реализовать эти функции

  • Практические вопросы

  • Справочные статьи / Документация

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

Например:
dataframe.groupby(level=’groupby_column’).agg({‘aggregate_column’: ‘aggregate_function’})

Такие тексты, как ‘dataframe’ и ‘groupby_column’ выделены жирным шрифтом и курсивом, что означает, что вы должны заменить их на фактические переменные.
Такие тексты, как ‘.groupby’ и ‘level’, которые не выделены жирным шрифтом и курсивом, должны оставаться неизменными для выполнения функции.

Предположим, Amazon просит найти общую стоимость, которую каждый пользователь потратил на свои заказы на amazon.
Реализация этой функции для данного набора данных будет выглядеть следующим образом:
amazon_orders.groupby(level=’user_id’).agg({‘cost’: ‘sum’})

Оглавление

  • Обзорная диаграмма оконных функций Python

  • Агрегат
    Группировать по
    Прокрутка
    Расширение

  • Ранжирование
    Номер строки

    reset_index()
    cumcount()

    Ранг

    ранг по умолчанию
    минимальный_ранг
    NA_bottom
    по убыванию

    Плотный ранг
    Процентный ранг
    N-Tile / qcut()

  • Значение
    Lag / Lead
    Первое / последнее / n-ое значение

Оконные функции Python

Хотя официальной классификации оконных функций Python не существует, это общие реализованные функции.

Агрегат

Вот некоторые распространенные типы агрегатных функций

  • Среднее
  • Максимальное
  • Min
  • Sum
  • Count

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

  • Группировка по
  • Свертывание
  • Развертывание

Пример

  • Группировка по: Facebook пытается найти средний доход Instagram за каждый год.
  • Скользящий: Facebook пытается найти скользящий средний доход Instagram за 3 года.
  • Расширяющийся: Facebook пытается найти кумулятивный средний доход Instagram с начальным размером в 2 года.

Группировка по

Группировка по агрегатам — это вычисление определенного столбца по статистической функции внутри каждой группы. Например, в наборе данных

Давайте воспользуемся вопросом от Amazon, чтобы объяснить эту тему. В этом вопросе нас просят вычислить процент от общей суммы расходов, потраченных покупателем на каждый заказ. Выведите имя покупателя, данные заказа (название товара) и процентное соотношение стоимости заказа к общей сумме расходов по всем заказам.

Помните, что при подходе к вопросам нужно следовать 3 шагам

  1. Задайте уточняющие вопросы
  2. Высказать предположения
  3. Попробуйте ответить на вопрос

Подходя к этим вопросам, поймите, какие столбцы нужно сгруппировать, а какие — агрегировать.
Для примера Amazon,
Группировать по: имя_клиента, идентификатор_заказа, данные_заказа
Агрегировать: total_order_cost

В этом вопросе есть 2 таблицы, которые нужно объединить, чтобы получить имя клиента, товар и расходы. После объединения обеих таблиц и фильтрации для получения необходимых столбцов, мы получим следующий набор данных.

Когда необходимые данные собраны в одной таблице, ими легче манипулировать.

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

Это общий формат того, как группировать по и агрегировать необходимые столбцы.
dataframe.groupby(level=’groupby_column’).agg({‘aggregate_column’: ‘aggregate_function’})

Что касается примера Amazon, вот код выполнения.

total_spending = customer_orders.groupby("first_name").agg({'total_order_cost' : 'sum'})

Этот код выведет следующий фрейм данных

После этого мы хотим добавить в объединенный фрейм данных столбец для представления общих расходов каждого человека.

Давайте объединим оба фрейма данных по фамилии_человека.

pd.merge(merged_dataframe, total_spending, how="left", on="first_name")

Теперь мы получим следующий набор данных

Как видно, столбец total_order_cost_y представляет общие расходы на одного человека, а total_order_cost_x — расходы на один заказ. После этого, это простое деление на 2 столбца для создания столбца процентной доли расходов И фильтрация вывода для получения необходимых столбцов.

result = df3[["first_name", "order_details", "percentage_total_cost"]]

Однако в некоторых ситуациях требуется сортировка значений внутри каждой группы. Именно здесь реализована функция sort_values().

Обратимся к примеру с вопросом amazon:

Предположим, интервьюер просит упорядочить процентные_суммы_стоимости в порядке убывания по человеку.

result = result.sort_values(by=['first_name', 'percentage_total_cost'], ascending = (True, False))

import pandas as pd
df = pd.merge(orders, customers, left_on="cust_id", right_on="id")
df1 = df[["first_name", "id_x", 'order_details', 'total_order_cost']]
df2 = df.groupby("first_name").agg({'total_order_cost' : 'sum'})
df3 = pd.merge(df1, df2, how="left", on="first_name")
df3["percentage_total_cost"] = df3["total_order_cost_x"] / df3["total_order_cost_y"]
result = df3[["first_name", "order_details", "percentage_total_cost"]]
result = result.sort_values(by=['first_name', 'percentage_total_cost'], ascending = (True, False))

Практика

  • https://platform.stratascratch.com/coding/9711-facilities-with-lots-of-inspections?python=
  • https://platform.stratascratch.com/coding/9899-percentage-of-total-spend?python=1
  • https://platform.stratascratch.com/coding/2044-most-senior-junior-employee?python=1

Ссылка

  • функция sort_values()
  • groupby() функция
  • Агрегация в справочнике Group By
  • функция groupby().agg()

Свернутая и развернутая функция

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

Эти изображения объясняют разницу между функциями сворачивания и разворачивания.

Функция сворачивания

Расширяющаяся функция

Разворачивающая и расширяющая функции начинаются с одного и того же размера окна, но расширяющая функция включает в себя все последующие значения за пределами начального размера окна.

Пример: AccuWeather, компания по прогнозированию погоды, пытается найти скользящее и расширяющееся среднее значение погоды в Сан-Франциско в январе на 10 дней.

Скользящее: Начиная с размера окна 10, мы берем среднюю температуру с 1 по 10 января. Далее мы берем 2 января по 11 января и так далее. Это показывает, что размер окна в скользящих функциях остается неизменным.

Расширение: Начиная с размера окна 10, мы берем среднюю температуру с 1 января по 10 января. Однако далее мы возьмем среднюю температуру с 1 по 11 января. Затем с 1 января по 12 января и так далее. Таким образом, размер окна «расширился».

Хотя существует множество агрегатных функций, которые могут быть использованы в функциях свертывания/расширения, в этой статье будут рассмотрены часто используемые функции (sum, average, max, min).

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

Скользящий агрегат

Реализация скользящих функций проста.

Общий формат:

DataSeries.rolling(window_size).aggregate_function()

Пример:
Температура в Сан-Франциско за первые 22 дня 2021 года. Найдем среднее значение, сумму, максимум и минимум скользящего временного интервала в 5 дней.

weather['Average'] = weather['Temperature'].rolling(5).mean()
weather['Sum'] = weather['Temperature'].rolling(5).sum()
weather['Max'] = weather['Temperature'].rolling(5).max()
weather['Min'] = weather['Temperature'].rolling(5).min()

После строки 4 скользящая функция для фиксированного окна размером 5 вычисляет среднее, сумму, максимум и минимум для значений температуры. Это означает, что в колонке среднего значения в строке 16 вычисляется среднее значение из строк 12, 13, 14, 15 и 16.

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

В этом случае нужно задать минимальное количество наблюдений для начала вычислений. Внутри функции rolling можно указать min_periods.

DataSeries.rolling(window_size, min_periods=minimum_observations).aggregate_function()

weather['Average'] = weather['Temperature'].rolling(5, min_periods=1).mean()
weather['Sum'] = weather['Temperature'].rolling(5, min_periods=2).sum()
weather['Max'] = weather['Temperature'].rolling(5, min_periods=3).max()
weather['Min'] = weather['Temperature'].rolling(5, min_periods=3).min()

Практика

  • https://platform.stratascratch.com/coding/10314-revenue-over-time?python=1

Ссылка

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rolling.html
  • https://towardsdatascience.com/dont-miss-out-on-rolling-window-functions-in-pandas-850b817131db

Расширяющийся агрегат

Расширяющая функция имеет аналогичную реализацию, что и скользящие функции.

DataSeries.expanding(minimum_observations).aggregate_function()

Важно помнить, что в отличие от скользящей функции, расширяющая функция не устанавливает размер окна, что обусловлено ее непостоянством. Задается минимальное_наблюдение, поэтому для строк меньше минимального_наблюдения будет установлено значение null.

Давайте воспользуемся тем же примером с температурой в Сан-Франциско, чтобы объяснить функцию расширения.

weather['Average'] = weather['Temperature'].expanding(5).mean()
weather['Sum'] = weather['Temperature'].expanding(5).sum()
weather['Max'] = weather['Temperature'].expanding(5).max()
weather['Min'] = weather['Temperature'].expanding(5).min()

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

import pandas as pd
weather = pd.DataFrame({'Temperature': [57, 54, 60, 54, 57, 58, 52, 52, 59, 54, 53, 57, 56, 60, 55, 58, 59, 64, 65, 66, 67, 74]})
weather['Rolling_Average'] = weather['Temperature'].rolling(5).mean()
weather['Rolling_Sum'] = weather['Temperature'].rolling(5).sum()
weather['Rolling_Max'] = weather['Temperature'].rolling(5).max()
weather['Rolling_Min'] = weather['Temperature'].rolling(5).min()
weather[‘Rolling_Average_minperiod’] = weather['Temperature'].rolling(5, min_periods=1).mean()
weather['Rolling_Sum_minperiod'] = weather['Temperature'].rolling(5, min_periods=2).sum()
weather['Rolling_Max_minperiod'] = weather['Temperature'].rolling(5, min_periods=3).max()
weather['Rolling_Min_minperiod'] = weather['Temperature'].rolling(5, min_periods=3).min()
weather['Expanding_Average'] = weather['Temperature'].expanding(5).mean()
weather['Expanding_Sum'] = weather['Temperature'].expanding(5).sum()
weather['Expanding_Max'] = weather['Temperature'].expanding(5).max()
weather['Expanding_Min'] = weather['Temperature'].expanding(5).min()
weather

Ссылка

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.expanding.html
  • https://towardsdatascience.com/window-functions-in-pandas-eaece0421f7
  • https://campus.datacamp.com/courses/manipulating-time-series-data-in-python/window-functions-rolling-expanding-metrics?ex=5

Рейтинг

Количество строк

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

  1. По всему датафрейму — reset_index()
  2. Внутри групп — cumcount()

Эти функции эквивалентны функции row_number() в SQL.

Давайте воспользуемся следующим набором данных для объяснения обеих концепций

Сброс_индекса

Внутри фрейма данных функция reset_index() выводит номер строки каждого ряда.

Общий формат для выполнения:
dataframe.reset_index()

Для извлечения n-го ряда используйте функцию .iloc()

Dataframe.iloc[nth_row]

cumcount()

Для подсчета количества строк в группах датафрейма необходимо реализовать функцию cumcount() в следующем формате

dataframe.groupby([‘column_names’]).cumcount()

Также не забудьте, что для того, чтобы начать подсчет строк с 1 вместо 0 по умолчанию, необходимо добавить +1 к функции cumcount().

Для примера набора данных реализация будет выглядеть следующим образом

df['Row_count'] = df.groupby(['c1', 'c2']).cumcount()+1

Это будет выходной результат

Теперь, когда у вас есть количество рядов в каждой группе, иногда вам нужно извлечь определенный индексный ряд каждой группы.

Например, компания просит извлечь 2-е индексированное значение в каждой группе. Мы можем извлечь его, вернув каждую строку со значением row_count равным 2.

Снова используя iloc, мы можем извлечь подмножество в следующем общем формате

Dataframe.loc[dataframe[имя_столбца] == индекс]

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

df.loc[df['Row_count'] == 2]

для получения подмножества

import pandas as pd
df = pd.DataFrame({'c1': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C'], 'c2':['X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'], 'v1':[3, 5, 7, 1, 3, 1, 3, 1, 7, 4, 1, 6]})
df['Row_count'] = df.groupby(['c1', 'c2']).cumcount()+1
df.loc[df['Row_count'] == 2]

Вопросы:

  • https://platform.stratascratch.com/coding/2004-number-of-comments-per-user-in-past-30-days?python=1
  • https://platform.stratascratch.com/coding/9716-top-3-facilities?python=1
  • https://platform.stratascratch.com/coding/10351-activity-rank?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html
  • https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.GroupBy.cumcount.html

Ранжирование

Функция ранжирования, как следует из названия, ранжирует значения на основе определенной переменной. Функция ранжирования работает несколько иначе, чем ее SQL-эквивалент.

Функция Rank() может быть выполнена в следующем общем формате

dataframe[имя_столбца].rank()

Возьмем следующий набор данных из документации по ранжированию Pandas.

И создадим 4 новых столбца, которые оба используют функцию rank(), чтобы лучше объяснить функцию и ее наиболее популярные параметры.

animal_legs['default_rank'] = animal_legs['Number_legs'].rank()
animal_legs['min_rank'] = animal_legs['Number_legs'].rank(method='min')
animal_legs['NA_bottom'] = animal_legs['Number_legs'].rank(method='min', na_option='bottom')
animal_legs['descending'] = animal_legs['Number_legs'].rank(method='min', ascending = False)

В этой функции мы ранжируем количество_ног для каждого животного.

Давайте разберемся, что представляет собой каждый из столбцов.

‘default_rank’

В стандартной функции rank() есть три важных момента, на которые следует обратить внимание.

  • Предполагается, что порядок возрастания истинный
  • Нулевые значения не ранжируются и остаются как null
  • Если n значений равны, ранговое разбиение усредняется между ними.

Ранговое разбиение по n значениям немного запутано, поэтому давайте подробнее остановимся на этом, чтобы лучше объяснить его.

В SQL для приведенного выше набора данных, поскольку и у кошки, и у собаки по 4 лапы, можно было бы предположить, что у обоих ранг = 2, а у паука со следующим по количеству лап рангом будет 4.

Вместо этого Pandas усредняет ранги «было бы» между кошкой и собакой.
Должны быть ранги 2 и 3, но поскольку кошка и собака имеют одинаковое значение, ранг равен среднему значению 2 и 3, то есть 2,5.

Давайте изменим пример животного, включив в него «осла», у которого 4 ноги.

У пингвина наименьшее количество ног — 2, поэтому его ранг = 1.

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

Если у нас есть 4 животных с 4 ногами, то будет взято среднее значение 2,3,4,5 = 3.5.

‘min_rank’

При установке параметра method=’min, вместо того, чтобы брать среднее значение, будет браться минимальный ранг между равными значениями.

Минимальный ранг — это то же самое, как работает функция rank в SQL.

В примере с животными ранг между собакой и кошкой теперь будет 2, а не 2,5.
А для примера с ослом ранг по-прежнему будет равен 2, в то время как для паука будет установлен ранг 5.

‘NA_bottom’

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

Установка опции na_option как bottom даст значение с самым высоким рангом, а установка как top даст значение с самым низким рангом.

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

‘descending’

Если вы хотите установить ранг в порядке убывания, установите параметр ascending как false.

Ссылаясь на пример с животными, мы устанавливаем параметр ascending в false, а метод — в minimum.

Вопросы:

  • https://platform.stratascratch.com/coding/10169-highest-total-miles?python=
  • https://platform.stratascratch.com/coding/10324-distances-traveled?python=
  • https://platform.stratascratch.com/coding/2070-top-three-classes?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rank.html

Плотный ранг

Плотный ранг похож на обычный ранг с небольшим отличием.

В обычной функции ранжирования номера рангов могут быть пропущены, в то время как в dense_rank они не пропускаются.

Например, в кадре данных о животных после [собака, кошка, осел] следующим значением был паук. При минимальном ранжировании он устанавливает пауков как ранг = 5, поскольку 2,3,4 технически установлены для кошки, собаки и осла.

В плотном ранге он установит ближайшие последовательные ранги, как показано выше. Вместо 5-го ранга, паук был установлен на 3-й ранг в dense_rank.

К счастью, для получения плотного ранга достаточно изменить параметр метода в функции ранга

animal_legs['dense_rank'] = animal_legs['Number_legs'].rank(method='dense')

Все остальные параметры, такие как na_option и ascending, также могут быть установлены вместе с методом dense, как уже упоминалось ранее.

Вопросы:

  • https://platform.stratascratch.com/coding/9701-3rd-most-reported-health-issues?python=1
  • https://platform.stratascratch.com/coding/2026-bottom-2-companies-by-mobile-usage
  • https://platform.stratascratch.com/coding/2019-top-2-users-with-most-calls?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rank.html
  • https://dfrieds.com/data-analysis/rank-method-python-pandas.html

Процентный ранг (Percentile)

Процентный ранг оконная функция python
Процентный ранг — это просто представление рангов по сравнению с самым высоким рангом.

Как видно из приведенного выше датафрейма животных, паук имеет ранг 5 как для default_rank, так и для min_rank. Поскольку 5 — это наивысший ранг, остальные значения будут сравниваться с ним.
Для кошки в default_rank она имеет значение 3, а 3 / 5 = 0,6 для default_pct_rank.
Для кошки в min_rank он имеет значение 2, а 2 / 5 = 0,4 для min_pct_rank.

Процентный ранг — это булев параметр, который может быть установлен

animal_legs['min_pct_rank'] = animal_legs['Number_legs'].rank(method='min', pct=True)

Вопросы:

  • https://platform.stratascratch.com/coding/10303-top-percentile-fraud?python=1
  • https://platform.stratascratch.com/coding/9611-find-the-80th-percentile-of-hours-studied?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rank.html
  • https://dfrieds.com/data-analysis/rank-method-python-pandas.html

import pandas as pd
import numpy as np
animal_legs = pd.DataFrame(data={'Animal': ['cat', 'penguin', 'dog', 'spider', 'snake', 'donkey'], 'Number_legs': [4, 2, 4, 8, np.nan, 4]})
animal_legs['default_rank'] = animal_legs['Number_legs'].rank()
animal_legs['min_rank'] = animal_legs['Number_legs'].rank(method='min')
animal_legs['NA_bottom'] = animal_legs['Number_legs'].rank(method='min', na_option='bottom')
animal_legs['descending'] = animal_legs['Number_legs'].rank(method='min', ascending = False)
animal_legs['dense_rank'] = animal_legs['Number_legs'].rank(method='dense')
animal_legs['default_pct_rank'] = animal_legs['Number_legs'].rank(pct=True)
animal_legs['min_pct_rank'] = animal_legs['Number_legs'].rank(method='min', pct=True)
animal_legs

N-Tile / qcut()

qcut() — не самая популярная функция, поскольку ранжирование на основе квантилей и перцентилей не так распространено. Несмотря на то, что она не так популярна, это все еще очень мощная функция!
Если вы не знаете взаимосвязь между квантилями и перцентилями, ознакомьтесь с этой статьей по статистике!

Давайте рассмотрим вопрос от DoorDash, чтобы объяснить, как используется qcut.

Вопрос просит нас найти нижние 2% набора данных, которые являются первым квантилем из 50-квантильного разбиения.

Общий формат, которого следует придерживаться при использовании qcut():
pd.qcut(dataseries, q=число_квантилей, labels = range(lower_bound, upper_bound))

Это подмножество набора данных, которое мы будем использовать для анализа использования функции qcut().

  • dataseries → Столбец для анализа, который в данном примере является total_order
  • number_quantiles → Количество квантилей для разделения, которое равно 50, так как в данном случае используется 50-квантильное разделение
  • labels → Диапазон ntiles, который в данном случае равен 1-50. Однако верхняя граница вычисляется как n-1. Поэтому если мы зададим диапазон 1-50, то верхняя граница будет равна 49, а не 50. Поэтому мы устанавливаем верхнюю границу как n+1, что в данном примере будет range(1,51).

Для данного примера это будет следующий код.

result[‘ntile’] = pd.qcut(result['total_order'],q=50, labels=range(1, 50))

Как видно из примера, ‘ntile’ был разделен и представляет собой квантиль.

Следует также отметить, что если диапазон меток не указан, возвращается диапазон квантилей.

Например, выполнение того же кода выше без диапазона меток:

result[‘ntile_range’] = pd.qcut(result['total_order'],q=50)

import pandas as pd
result = doordash_delivery[doordash_delivery['customer_placed_order_datetime'].between('2020-05-01', '2020-05-31')].groupby("restaurant_id")["order_total"].sum().to_frame('total_order').reset_index()
result['ntile'] = pd.qcut(result['total_order'],q=50, labels=range(1, 50), duplicates = 'drop').values.tolist()
result['ntile_range'] = pd.qcut(result['total_order'],q=50, duplicates = 'drop').values.tolist()
result

Вопросы:

  • qcut() → https://platform.stratascratch.com/coding/2036-lowest-revenue-generated-restaurants?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.qcut.html
  • https://towardsdatascience.com/all-pandas-qcut-you-should-know-for-binning-numerical-data-based-on-sample-quantiles-c8b13a8ed844

Значение

Lag / Lead

Функции Lag и Lead используются для представления другого столбца, но сдвинутого на одну или несколько строк.

Давайте воспользуемся набором данных, предоставленным Facebook (Meta), который представляет собой общую стоимость заказов по каждому месяцу.

В столбце ‘Lag’ мы видим, что значения были сдвинуты вниз на одну строку. Значение 305, которое является общей стоимостью заказа (total_order_cost) за январь, появляется в колонке ‘Lag’, но в той же строке, что и февраль.

В столбце ‘Lead’ происходит обратное. Строки сдвигаются вверх на единицу, поэтому 285, которая является общей_стоимостью_заказа для февраля, появляется в колонке «Лидер» в январе.

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

Общий формат, которому можно следовать:
dataframe[‘shifting_column’].shift(number_shift)

Код, используемый для данных:

orders['Lag'] = orders['total_order_cost'].shift(1)
orders['Lead'] = orders['total_order_cost'].shift(-1)

Также необходимо помнить о нулевых значениях, которые появляются в результате сдвига. Как видно, в столбце Lag и Lead имеется 1 нулевое значение (NaN), так как значения были сдвинуты на 1. Будет n рядов нулевых значений, так как ряд данных был сдвинут на n рядов. Таким образом, первые n строк столбца ‘Lag’ и последние n строк столбца ‘Lead’ будут иметь нулевые значения.
Если вы хотите заменить нулевые значения, образовавшиеся в результате сдвига, вы можете использовать параметр fill_value.

Выполняем код с обновленными параметрами

orders['Lag'] = orders['total_order_cost'].shift(1, fill_value = 0)
orders['Lead'] = orders['total_order_cost'].shift(-1, fill_value = 0)

На выходе получаем следующее

import pandas as pd
import numpy as np
orders['order_date'] = orders['order_date'].apply(pd.to_datetime)
orders['order_month'] = orders['order_date'].dt.month
orders.loc[(orders.order_month == 1),'order_month'] = 'January'
orders.loc[(orders.order_month == 2),'order_month'] = 'February'
orders.loc[(orders.order_month == 3),'order_month'] = 'March'
orders.loc[(orders.order_month == 4),'order_month'] = 'April'
orders['order_month'] = pd.Categorical(orders['order_month'], ["January", "February", "March", "April"])
orders = orders[['order_month', 'total_order_cost']]
orders = orders.sort_values(by=['order_month'])
orders = orders.groupby("order_month").agg({'total_order_cost' : 'sum'})
orders['Lag'] = orders['total_order_cost'].shift(1, fill_value = 0)
orders['Lead'] = orders['total_order_cost'].shift(-1, fill_value = 0)
orders

Вопросы:

  • https://platform.stratascratch.com/coding/9637-growth-of-airbnb?python=
  • https://platform.stratascratch.com/coding/9714-dates-of-inspection?python=
  • https://platform.stratascratch.com/coding/2045-days-without-hiringtermination?python=1

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html

Первое/последнее/ n-ое значение

Найти n-ое значение (включая первое и последнее) в группах набора данных довольно просто и в Python.

Давайте воспользуемся тем же набором данных заказов Facebook, который использовался в разделе «Отставание/опережение».

Как видно здесь, order_date упорядочен от самого раннего к самому позднему.

Давайте найдем первый заказ каждого месяца с помощью функции nth().

Общий формат:
dataframe.groupby(‘groupby_column’).nth(nth_value)

nth_value представляет собой индексируемое значение
nth_value в функции nth() работает так же, как извлечение nth_value в списке.
0 представляет первое значение
-1 представляет последнее значение

Используя следующий код:

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

orders.groupby('order_month').nth(0)['total_order_cost'].reset_index()

Теперь, если вы хотите присоединить n-ое значение к соответствующим сгруппированным по столбцам исходного датафрейма, вы можете использовать функцию слияния, аналогично тому, как функция слияния применялась в агрегатных функциях, упомянутых выше. Не забудьте также извлечь столбец для объединения! В данном примере это будет индексный столбец ‘order_month’, для которого следует использовать функцию reset_index().

import pandas as pd
orders['order_date'] = orders['order_date'].apply(pd.to_datetime)
orders['order_month'] = orders['order_date'].dt.month
orders = orders.sort_values(by=['order_date'])
ordered_group = orders.groupby('order_month').nth(0)['total_order_cost'].reset_index()

Ссылка:

  • https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.GroupBy.nth.html

Составленные практические вопросы

Агрегировать
Группа по
  • https://platform.stratascratch.com/coding/9711-facilities-with-lots-of-inspections?python=
  • https://platform.stratascratch.com/coding/9899-percentage-of-total-spend?python=1
  • https://platform.stratascratch.com/coding/2044-most-senior-junior-employee?python=1
Прокат
  • https://platform.stratascratch.com/coding/10314-revenue-over-time?python=1
Расширение
  • [[[ Без вопросов]]
Рейтинг
Row_number()
  • https://platform.stratascratch.com/coding/2004-number-of-comments-per-user-in-past-30-days?python=1
  • https://platform.stratascratch.com/coding/9716-top-3-facilities?python=
  • https://platform.stratascratch.com/coding/10351-activity-rank?python=1
ранг()
  • https://platform.stratascratch.com/coding/10169-highest-total-miles?python=
  • https://platform.stratascratch.com/coding/10324-distances-traveled?python=
  • https://platform.stratascratch.com/coding/2070-top-three-classes?python=1
плотный_ранг()
  • https://platform.stratascratch.com/coding/9701-3rd-most-reported-health-issues?python=
  • https://platform.stratascratch.com/coding/2026-bottom-2-companies-by-mobile-usage
  • https://platform.stratascratch.com/coding/2019-top-2-users-with-most-calls?python=1
процентный_ранг()
  • https://platform.stratascratch.com/coding/10303-top-percentile-fraud?python=1
  • https://platform.stratascratch.com/coding/9611-find-the-80th-percentile-of-hours-studied?python=1
ntile() / qcut()
  • https://platform.stratascratch.com/coding/2036-lowest-revenue-generated-restaurants?python=1
Значение
Отставание/Отставание
  • https://platform.stratascratch.com/coding/9637-growth-of-airbnb?python=
  • https://platform.stratascratch.com/coding/9714-dates-of-inspection?python=
  • https://platform.stratascratch.com/coding/2045-days-without-hiringtermination?python=1
Первый / Последний / nth_value()
  • [[[ Без вопросов]]

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *