Python – вычесть дату по первой записи?

Я использую библиотеку Polars в Python для управления некоторыми кадрами данных.

Я пытаюсь сделать следующее: :

Для некоторого фрейма данных:

Человек.. Бороться с На А Б 3 января А С 4 января А Д 5 января А Э 5 января А Б 10 января А Б 20 января А С 20 января

Я хочу вернуть «расстояние» между текущей парой бойцов и их первым боем, например: :

Человек.. Бороться с На Расстояние А Б 3 января 0 дней А С 4 января 0 дней А Д 5 января 0 дней А Э 5 января 0 дней А Б 10 января 7 дней (т.е. 10 января – 3 января); (ТекущаяДата — ABFirstFight) А Б 20 января 17 дней (т.е. 20 января – 3 января); (ТекущаяДата — ABFirstFight) А С 20 января 16 дней (т.е. 20 января – 4 января); (Текущая дата — ACFirstFight)

<Что я пробовал>:

  1. функция Polars «первая»: вернула только заголовок кадра данных.
  2. «Первая» функция Polars с некоторыми комбинациями функций «over»/«group_by»/«rolling»: вернула несколько чисел, но я не могу понять, почему результат был таким

Есть ли у кого-нибудь совет, как это сделать?

Я думаю, что мне, возможно, придется использовать некоторую комбинацию «group_by» или «over», «first» и, возможно, «sub» (чтобы вычесть две даты?), но я не уверен, как действовать. Самое сложное для меня — попытаться извлечь первую запись данной группы (например, первую запись даты пары A-B или пары AC и т. д.).

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот один из способов сделать это:

Сгруппируйте фрейм данных по [person, fight_with], выберите минимум on, а затем соедините его с исходным фреймом данных.

Вот код:

import polars as pl

df = pl.DataFrame(
    {
        "person": ["A", "A", "A", "A", "A", "A", "A"],
        "fight_with": ["B", "C", "D", "E", "B", "B", "C"],
        "on": [3, 4, 5, 5, 10, 20, 20],
    }
)

first_fight = df.group_by("person", "fight_with").agg(pl.min("on").alias("min_on"))

df = df.join(first_fight, on=["person", "fight_with"]).with_columns(
    distance=pl.col("on") - pl.col("min_on")
)

print(df)

Выход:

shape: (7, 5)
┌────────┬────────────┬─────┬────────┬──────────┐
│ person ┆ fight_with ┆ on  ┆ min_on ┆ distance │
│ ---    ┆ ---        ┆ --- ┆ ---    ┆ ---      │
│ str    ┆ str        ┆ i64 ┆ i64    ┆ i64      │
╞════════╪════════════╪═════╪════════╪══════════╡
│ A      ┆ B          ┆ 3   ┆ 3      ┆ 0        │
│ A      ┆ C          ┆ 4   ┆ 4      ┆ 0        │
│ A      ┆ D          ┆ 5   ┆ 5      ┆ 0        │
│ A      ┆ E          ┆ 5   ┆ 5      ┆ 0        │
│ A      ┆ B          ┆ 10  ┆ 3      ┆ 7        │
│ A      ┆ B          ┆ 20  ┆ 3      ┆ 17       │
│ A      ┆ C          ┆ 20  ┆ 4      ┆ 16       │
└────────┴────────────┴─────┴────────┴──────────┘

Спасибо! В качестве примечания можно также использовать следующее: agg(pl.first("on")

user24758287 20.05.2024 12:26

Да, pl.first("on") даст тот же результат быстрее, если ваш массив отсортирован по on.

Dogbert 21.05.2024 12:51

Как вы уже сказали, вы можете получить первый .over() каждой группы.

df.with_columns(
   pl.format("{} - {}", pl.col("On"), pl.col("On").first())
     .over("Person..", "Fight with")
)
shape: (7, 3)
┌──────────┬────────────┬────────────────┐
│ Person.. ┆ Fight with ┆ On             │
│ ---      ┆ ---        ┆ ---            │
│ str      ┆ str        ┆ str            │
╞══════════╪════════════╪════════════════╡
│ A        ┆ B          ┆ 3 Jan - 3 Jan  │
│ A        ┆ C          ┆ 4 Jan - 4 Jan  │
│ A        ┆ D          ┆ 5 Jan - 5 Jan  │
│ A        ┆ E          ┆ 5 Jan - 5 Jan  │
│ A        ┆ B          ┆ 10 Jan - 3 Jan │
│ A        ┆ B          ┆ 20 Jan - 3 Jan │
│ A        ┆ C          ┆ 20 Jan - 4 Jan │
└──────────┴────────────┴────────────────┘

См. Функции окна в руководстве пользователя:

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