Я хотел бы спросить, знает ли кто-нибудь, как выполнять скользящую индексацию в полярах? Я лично попробовал несколько решений, которые мне не помогли (покажу их ниже):
Что я хотел бы сделать: индексировать количество вхождений за последние X дней по имени. Пример. Допустим, я хотел бы проиндексировать события за последние 2 дня:
В этом случае счетчик сбрасывается на «1», начиная с последних X дней (например, для 3 января 23 года он начинается с «1» со 2 января 23 года) или если обнаружено новое имя.
Что я пробовал:
df.groupby_rolling(index_column='Date', period='2d', by='Name', check_sorted=False).agg((pl.col("Date").rank(method='ordinal')).alias("Counter"))
Вышеупомянутое не работает, потому что выводит:
df.with_columns( Counter=pl.col("mask").rolling_sum(window_size='2d', by = "Date") )
Где я создал столбец «Маска», который представляет собой просто столбец «1», и попытался их просуммировать, но выводит:
И он также не может правильно обработать «Нового парня», потому что Rolling_sum не может сделать по = «Имя», «Дата»
df.with_columns(Counter = pl.col("Date").rank(method='ordinal').over(["Name", "Date"]) )
Приведенный выше код работает правильно, но его можно использовать только для индексации в течение одного дня (т. е. period="1d").
Дополнительные примечания: я также сделал это в Excel, а также использовал метод грубого/необработанного цикла «for». Оба работали отлично, однако им приходилось сталкиваться с огромными объемами данных.
Что я прочитал: Некоторые ссылки для помощи в ответах: (Большинство из них не сработало, потому что у них фиксированное скользящее окно вместо динамического окна по «Дате»)
Как реализовать скользящий ранг в Polars версии 0.19
https://github.com/pola-rs/polars/issues/4808
Как сделать group_by_rolling сгруппированным по дням и часам в полярах в Python?
Как группировать и катать поляры?
https://docs.pola.rs/py-polars/html/reference/series/api/polars.Series.rank.html
https://docs.pola.rs/py-polars/html/reference/dataframe/api/polars.DataFrame.groupby_rolling.html
Вы хотите сказать, что начинаете только со столбцов «Имя», «Дата» и «Счетчик» — это ожидаемый результат, который вы хотите сгенерировать?
@Hericks, пример ожидаемого результата находится в разделе «Что я хотел бы сделать: индексировать количество вхождений за последние X дней по имени».
@jqurious Ага! Это верно!
Вы можете начать с подхода, дающего максимальное значение для каждой группы (используя pl.len()
внутри агрегирования), а затем выполнить постобработку столбца Counter
, чтобы его значения увеличивались внутри каждой группы.
(
df
.rolling(index_column = "Date", period = "2d", group_by = "Name", check_sorted=False)
.agg(
pl.len().alias("Counter")
)
.with_columns(
(pl.col("Counter") - pl.len() + 1 + pl.int_range(pl.len())).over("Name", "Date")
)
)
shape: (11, 3)
┌─────────┬────────────┬─────────┐
│ Name ┆ Date ┆ Counter │
│ --- ┆ --- ┆ --- │
│ str ┆ date ┆ i64 │
╞═════════╪════════════╪═════════╡
│ John ┆ 2023-01-01 ┆ 1 │
│ John ┆ 2023-01-01 ┆ 2 │
│ John ┆ 2023-01-01 ┆ 3 │
│ John ┆ 2023-01-01 ┆ 4 │
│ John ┆ 2023-01-02 ┆ 5 │
│ John ┆ 2023-01-02 ┆ 6 │
│ John ┆ 2023-01-02 ┆ 7 │
│ John ┆ 2023-01-02 ┆ 8 │
│ John ┆ 2023-01-03 ┆ 5 │
│ John ┆ 2023-01-03 ┆ 6 │
│ New Guy ┆ 2023-01-01 ┆ 1 │
└─────────┴────────────┴─────────┘
Объяснение. После агрегирования столбец Counter
примет постоянное значение V в каждой группе имени-даты длиной L. Цель состоит в том, чтобы вместо этого заставить Counter
принимать значения V-L+1 в V (по одному значению для каждой строки).
Поэтому мы можем
Counter
и
Можете ли вы также поделиться примером ожидаемого результата? Это облегчило бы предложение подходящего решения.