Вопрос или проблема
Я пытаюсь выполнить join_asof
в Polars, который будет смотреть только назад во времени, игнорируя совпадения в одной строке. В частности, я хочу, чтобы он находил последнюю строку, где Team
и Field
совпадают точно, но только если значение Wk
меньше, чем значение Wk
в текущей строке.
Цель состоит в том, чтобы получить последний GeneralLambda
для недавних игр, либо “Гостевой”, либо “Домашний”, исключая текущую игру. Я думал, что лучший способ сделать это – использовать join_asof
, но у меня возникают трудности с тем, как сделать так, чтобы он учитывал только прошлые строки и совпадал по обеим Team
и Field
.
Вот пример DataFrame для иллюстрации:
Сезон | Wk | Команда | Поле | GeneralLambda |
---|---|---|---|---|
2024 | 25 | КомандаA | Гостевой | 2.123456 |
2024 | 25 | КомандаB | Домашний | 1.234567 |
2024 | 25 | КомандаC | Гостевой | 0.987654 |
2024 | 25 | КомандаD | Домашний | 1.345678 |
2024 | 25 | КомандаE | Гостевой | 1.456789 |
2024 | 26 | КомандаA | Домашний | 1.234567 |
2024 | 26 | КомандаB | Гостевой | 1.345678 |
2024 | 26 | КомандаC | Домашний | 0.876543 |
2024 | 26 | КомандаD | Гостевой | 1.456789 |
2024 | 26 | КомандаE | Домашний | 1.567890 |
2024 | 27 | КомандаA | Гостевой | 2.278759 |
2024 | 27 | КомандаB | Гостевой | 1.103829 |
2024 | 27 | КомандаC | Домашний | 0.992563 |
2024 | 27 | КомандаD | Домашний | 1.089324 |
2024 | 27 | КомандаE | Домашний | 1.074221 |
Для каждой строки мне нужно объединить её с последней совпадающей строкой, где:
Team
совпадает,Field
совпадает,Wk
меньше, чем значениеWk
в текущей строке.
Я надеюсь, что DataFrame выглядит так:
Сезон | Wk | Команда | Поле | GeneralLambda | Prev_GeneralLambda |
---|---|---|---|---|---|
2024 | 25 | КомандаA | Гостевой | 2.123456 | ALastAwayValue |
2024 | 25 | КомандаB | Домашний | 1.234567 | BLastHomeValue |
2024 | 25 | КомандаC | Гостевой | 0.987654 | CLastAwayValue |
2024 | 25 | КомандаD | Домашний | 1.345678 | DLastHomeValue |
2024 | 25 | КомандаE | Гостевой | 1.456789 | ELastAwayValue |
2024 | 26 | КомандаA | Домашний | 1.234567 | ALastHomeValue |
2024 | 26 | КомандаB | Гостевой | 1.345678 | BLastAwayValue |
2024 | 26 | КомандаC | Домашний | 0.876543 | CLastHomeValue |
2024 | 26 | КомандаD | Гостевой | 1.456789 | DLastAwayValue |
2024 | 26 | КомандаE | Домашний | 1.567890 | ELastHomeValue |
2024 | 27 | КомандаA | Гостевой | 2.278759 | 2.123456 |
2024 | 27 | КомандаB | Гостевой | 1.103829 | 1.345678 |
2024 | 27 | КомандаC | Домашний | 0.992563 | 0.876543 |
2024 | 27 | КомандаD | Домашний | 1.089324 | 1.345678 |
2024 | 27 | КомандаE | Домашний | 1.074221 | 1.567890 |
Есть ли способ сделать это в Polars?
(
df.sort("Wk")
.with_columns(
pl.col("GeneralLambda")
.shift(1)
.fill_null(pl.col("Team").str.tail(1) + "Last" + pl.col("Field") + "Value")
.over("Team","Field")
.alias("Prev_GeneralLambda")
)
)
shape: (15, 6)
┌────────┬─────┬───────┬───────┬───────────────┬────────────────────┐
│ Сезон ┆ Wk ┆ Команда ┆ Поле ┆ GeneralLambda ┆ Prev_GeneralLambda │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ str ┆ str ┆ f64 ┆ str │
╞════════╪═════╪═══════╪═══════╪═══════════════╪════════════════════╡
│ 2024 ┆ 25 ┆ КомандаA ┆ Гостевой ┆ 2.123456 ┆ ALastAwayValue │
│ 2024 ┆ 25 ┆ КомандаB ┆ Домашний ┆ 1.234567 ┆ BLastHomeValue │
│ 2024 ┆ 25 ┆ КомандаC ┆ Гостевой ┆ 0.987654 ┆ CLastAwayValue │
│ 2024 ┆ 25 ┆ КомандаD ┆ Домашний ┆ 1.345678 ┆ DLastHomeValue │
│ 2024 ┆ 25 ┆ КомандаE ┆ Гостевой ┆ 1.456789 ┆ ELastAwayValue │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 2024 ┆ 27 ┆ КомандаA ┆ Гостевой ┆ 2.278759 ┆ 2.123456 │
│ 2024 ┆ 27 ┆ КомандаB ┆ Гостевой ┆ 1.103829 ┆ 1.345678 │
│ 2024 ┆ 27 ┆ КомандаC ┆ Домашний ┆ 0.992563 ┆ 0.876543 │
│ 2024 ┆ 27 ┆ КомандаD ┆ Домашний ┆ 1.089324 ┆ 1.345678 │
│ 2024 ┆ 27 ┆ КомандаE ┆ Домашний ┆ 1.074221 ┆ 1.56789 │
└────────┴─────┴───────┴───────┴───────────────┴────────────────────┘
Ответ или решение
Для выполнения операции join_asof
в библиотеке Polars с учетом только обратных совпадений по заранее определенным условиям, вы можете воспользоваться следующим подходом. Цель состоит в том, чтобы для каждой строки в DataFrame найти последнюю строку, где совпадают значения в столбцах Team
и Field
, и при этом значение Wk
должно быть меньше, чем значение Wk
текущей строки.
Шаги реализации
-
Сортировка DataFrame: Начнем с того, что необходимо отсортировать DataFrame по столбцу
Wk
, чтобы обеспечить корректный порядок для операции "асинхронного соединения". -
Создание нового столбца с предыдущими значениями: Используя метод
shift
, мы можем создать новый столбец, который будет содержать значениеGeneralLambda
предыдущей строки для текущей группыTeam
иField
. -
Фильтрация и условное заполнение: Для обеспечения правильности, после создания нового столбца, нужно заполнить его значениями только для тех строк, которые соответствуют условиям.
Пример кода
Вот пример Python-кода, который демонстрирует описанные шаги:
import polars as pl
# Исходный DataFrame
data = {
"Season": [2024] * 15,
"Wk": [25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27],
"Team": ["TeamA", "TeamB", "TeamC", "TeamD", "TeamE",
"TeamA", "TeamB", "TeamC", "TeamD", "TeamE",
"TeamA", "TeamB", "TeamC", "TeamD", "TeamE"],
"Field": ["Away", "Home", "Away", "Home", "Away",
"Home", "Away", "Home", "Away", "Home",
"Away", "Away", "Home", "Home", "Home"],
"GeneralLambda": [2.123456, 1.234567, 0.987654, 1.345678, 1.456789,
1.234567, 1.345678, 0.876543, 1.456789, 1.567890,
2.278759, 1.103829, 0.992563, 1.089324, 1.074221],
}
df = pl.DataFrame(data)
# Выполнение join_asof
result = (
df.sort("Wk")
.with_columns(
pl.col("GeneralLambda")
.shift(1)
.over("Team", "Field")
.alias("Prev_GeneralLambda")
)
.filter(
(pl.col("Wk") > pl.col("Wk").shift(1)) # Убедитесь, что Wk меньше
)
)
print(result)
Описание решения
-
Сортировка: Убедитесь, что DataFrame отсортирован по
Wk
перед выполнением join. -
Использование
shift
: Методshift(1)
отбирает значениеGeneralLambda
из предыдущей строки в рамках группы, что позволяет возвращать только предыдущие значения. -
Фильтрация: Фильтруем результаты, чтобы оставить только те строки, где
Wk
текущей строки больше, обеспечивая таким образом, что мы рассматриваем только предыдущие значения.
Подведение итогов
Данный код эффективно позволяет извлекать значения GeneralLambda
для заданных условий, отображая необходимые данные в DataFrame, что облегчает анализ спортивных данных по командам. Использование библиотеки Polars существенно ускоряет операции с большими данными благодаря высокопроизводительным алгоритмам. Убедитесь, что ваша версия библиотеки Polars обновлена до последней, чтобы использовать все доступные функции.