polars.LazyFrame.group_by_dynamic
-
Группировка по значению времени (или значению индекса типа Int32, Int64).
Вычисляются временные окна, и строки распределяются по окнам. В отличие от обычной группировки, одна строка может входить в несколько групп. По умолчанию окна выглядят так:
- [start, start + period)
- [start + every, start + every + period)
- [start + 2*every, start + 2*every + period)
- …
где
startопределяется параметрамиstart_by,offset,everyи самой ранней точкой данных. Подробности см. в описании аргументаstart_by.Предупреждение
Столбец индекса должен быть отсортирован по возрастанию. Если передан
group_by, столбец индекса должен быть отсортирован по возрастанию внутри каждой группы.Изменено в версии 0.20.14: Параметр
byбыл переименован вgroup_by.- Параметры:
-
- index_column
-
Столбец, используемый для группировки по временному окну. Обычно имеет тип Date/Datetime. Этот столбец должен быть отсортирован по возрастанию (или, если указано
group_by, он должен быть отсортирован по возрастанию внутри каждой группы).При динамической группировке по индексам тип данных должен быть одним из {Int32, Int64}. Обратите внимание: Int32 временно приводится к Int64, поэтому, если важна производительность, используйте столбец Int64.
- every
-
интервал окна
- period
-
длина окна; если значение равно None, она будет равна «every»
- offset
-
смещение окна; не применяется, если
start_byравно ‘datapoint’. По умолчанию равно нулю. - include_boundaries
-
Добавить нижнюю и верхнюю границы окна в столбцы “_lower_boundary” и “_upper_boundary”. Это повлияет на производительность, так как усложнит распараллеливание.
-
closed{‘left’, ‘right’, ‘both’, ‘none’} -
Определяет, какие стороны временного интервала являются закрытыми (включительными).
-
label{‘left’, ‘right’, ‘datapoint’} -
Определяет, какую метку использовать для окна:
- ‘left’: нижняя граница окна
- ‘right’: верхняя граница окна
- ‘datapoint’: первое значение столбца индекса в данном окне. Если метка не должна совпадать с одной из границ, выберите этот вариант для максимальной производительности
- group_by
-
Также группировать по этому столбцу или этим столбцам
-
start_by{‘window’, ‘datapoint’, ‘monday’, ‘tuesday’, ‘wednesday’, ‘thursday’, ‘friday’, ‘saturday’, ‘sunday’} -
Стратегия определения начала первого окна.
- ‘window’: начать с самой ранней временной метки, округлить её с помощью
every, а затем добавитьoffset. Обратите внимание: недельные окна начинаются в понедельник. - ‘datapoint’: начать с первой встреченной точки данных.
-
день недели (применяется, только если
everyсодержит'w'):- ‘monday’: начать окно с понедельника перед первой точкой данных.
- ‘tuesday’: начать окно со вторника перед первой точкой данных.
- …
- ‘sunday’: начать окно с воскресенья перед первой точкой данных.
Затем полученное окно сдвигается назад, пока самая ранняя точка данных не окажется внутри него или перед ним.
- ‘window’: начать с самой ранней временной метки, округлить её с помощью
- Возвращает:
-
- LazyGroupBy
-
Объект, для которого можно вызвать
.agg, чтобы выполнить агрегацию по группам. Результат будет отсортирован поindex_column(обратите внимание: если переданы столбцыgroup_by, сортировка будет выполнена только внутри каждой группы).
См. также
Примечания
-
Если вы переходите с pandas, то
# polars df.group_by_dynamic("ts", every="1d").agg(pl.col("value").sum())эквивалентно
# pandas df.set_index("ts").resample("D")["value"].sum().reset_index()однако, в отличие от pandas, polars не добавляет дополнительные строки для пустых окон. Если требуется, чтобы
index_columnимели равномерный шаг, объедините эту операцию сDataFrame.upsample(). -
Аргументы
every,periodиoffsetзадаются с помощью следующего строкового формата:- 1ns (1 наносекунда)
- 1us (1 микросекунда)
- 1ms (1 миллисекунда)
- 1s (1 секунда)
- 1m (1 минута)
- 1h (1 час)
- 1d (1 календарный день)
- 1w (1 календарная неделя)
- 1mo (1 календарный месяц)
- 1q (1 календарный квартал)
- 1y (1 календарный год)
- 1i (1 единица индекса)
Их можно объединять (кроме
every): “3d12h4m25s” # 3 дня, 12 часов, 4 минуты и 25 секундПод «календарным днём» понимается соответствующее время следующего дня (который может длиться не 24 часа из-за перехода на летнее время). То же относится к «календарной неделе», «календарному месяцу», «календарному кварталу» и «календарному году».
При group_by_dynamic по целочисленному столбцу окна задаются следующим образом:
- “1i” # длина 1
- “10i” # длина 10
Примеры
>>> from datetime import datetime >>> lf = pl.LazyFrame( ... { ... "time": pl.datetime_range( ... start=datetime(2021, 12, 16), ... end=datetime(2021, 12, 16, 3), ... interval="30m", ... eager=True, ... ), ... "n": range(7), ... } ... ) >>> lf.collect() shape: (7, 2) ┌─────────────────────┬─────┐ │ time ┆ n │ │ --- ┆ --- │ │ datetime[μs] ┆ i64 │ ╞═════════════════════╪═════╡ │ 2021-12-16 00:00:00 ┆ 0 │ │ 2021-12-16 00:30:00 ┆ 1 │ │ 2021-12-16 01:00:00 ┆ 2 │ │ 2021-12-16 01:30:00 ┆ 3 │ │ 2021-12-16 02:00:00 ┆ 4 │ │ 2021-12-16 02:30:00 ┆ 5 │ │ 2021-12-16 03:00:00 ┆ 6 │ └─────────────────────┴─────┘Группировка по окнам длительностью 1 час.
>>> lf.group_by_dynamic("time", every="1h", closed="right").agg( ... pl.col("n") ... ).collect() shape: (4, 2) ┌─────────────────────┬───────────┐ │ time ┆ n │ │ --- ┆ --- │ │ datetime[μs] ┆ list[i64] │ ╞═════════════════════╪═══════════╡ │ 2021-12-15 23:00:00 ┆ [0] │ │ 2021-12-16 00:00:00 ┆ [1, 2] │ │ 2021-12-16 01:00:00 ┆ [3, 4] │ │ 2021-12-16 02:00:00 ┆ [5, 6] │ └─────────────────────┴───────────┘Границы окна также можно добавить в результат агрегации
>>> lf.group_by_dynamic( ... "time", every="1h", include_boundaries=True, closed="right" ... ).agg(pl.col("n").mean()).collect() shape: (4, 4) ┌─────────────────────┬─────────────────────┬─────────────────────┬─────┐ │ _lower_boundary ┆ _upper_boundary ┆ time ┆ n │ │ --- ┆ --- ┆ --- ┆ --- │ │ datetime[μs] ┆ datetime[μs] ┆ datetime[μs] ┆ f64 │ ╞═════════════════════╪═════════════════════╪═════════════════════╪═════╡ │ 2021-12-15 23:00:00 ┆ 2021-12-16 00:00:00 ┆ 2021-12-15 23:00:00 ┆ 0.0 │ │ 2021-12-16 00:00:00 ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 00:00:00 ┆ 1.5 │ │ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ 3.5 │ │ 2021-12-16 02:00:00 ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 02:00:00 ┆ 5.5 │ └─────────────────────┴─────────────────────┴─────────────────────┴─────┘При closed=”left” окно не включает правый конец интервала: [lower_bound, upper_bound)
>>> lf.group_by_dynamic("time", every="1h", closed="left").agg( ... pl.col("n") ... ).collect() shape: (4, 2) ┌─────────────────────┬───────────┐ │ time ┆ n │ │ --- ┆ --- │ │ datetime[μs] ┆ list[i64] │ ╞═════════════════════╪═══════════╡ │ 2021-12-16 00:00:00 ┆ [0, 1] │ │ 2021-12-16 01:00:00 ┆ [2, 3] │ │ 2021-12-16 02:00:00 ┆ [4, 5] │ │ 2021-12-16 03:00:00 ┆ [6] │ └─────────────────────┴───────────┘При closed=”both” значения времени на границах окна входят в 2 группы.
>>> lf.group_by_dynamic("time", every="1h", closed="both").agg( ... pl.col("n") ... ).collect() shape: (4, 2) ┌─────────────────────┬───────────┐ │ time ┆ n │ │ --- ┆ --- │ │ datetime[μs] ┆ list[i64] │ ╞═════════════════════╪═══════════╡ │ 2021-12-16 00:00:00 ┆ [0, 1, 2] │ │ 2021-12-16 01:00:00 ┆ [2, 3, 4] │ │ 2021-12-16 02:00:00 ┆ [4, 5, 6] │ │ 2021-12-16 03:00:00 ┆ [6] │ └─────────────────────┴───────────┘Динамическую группировку также можно сочетать с группировкой по обычным ключам
>>> lf = lf.with_columns(groups=pl.Series(["a", "a", "a", "b", "b", "a", "a"])) >>> lf.collect() shape: (7, 3) ┌─────────────────────┬─────┬────────┐ │ time ┆ n ┆ groups │ │ --- ┆ --- ┆ --- │ │ datetime[μs] ┆ i64 ┆ str │ ╞═════════════════════╪═════╪════════╡ │ 2021-12-16 00:00:00 ┆ 0 ┆ a │ │ 2021-12-16 00:30:00 ┆ 1 ┆ a │ │ 2021-12-16 01:00:00 ┆ 2 ┆ a │ │ 2021-12-16 01:30:00 ┆ 3 ┆ b │ │ 2021-12-16 02:00:00 ┆ 4 ┆ b │ │ 2021-12-16 02:30:00 ┆ 5 ┆ a │ │ 2021-12-16 03:00:00 ┆ 6 ┆ a │ └─────────────────────┴─────┴────────┘ >>> lf.group_by_dynamic( ... "time", ... every="1h", ... closed="both", ... group_by="groups", ... include_boundaries=True, ... ).agg(pl.col("n")).collect() shape: (6, 5) ┌────────┬─────────────────────┬─────────────────────┬─────────────────────┬───────────┐ │ groups ┆ _lower_boundary ┆ _upper_boundary ┆ time ┆ n │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ datetime[μs] ┆ datetime[μs] ┆ datetime[μs] ┆ list[i64] │ ╞════════╪═════════════════════╪═════════════════════╪═════════════════════╪═══════════╡ │ a ┆ 2021-12-16 00:00:00 ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 00:00:00 ┆ [0, 1, 2] │ │ a ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ [2] │ │ a ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 02:00:00 ┆ [5, 6] │ │ a ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 04:00:00 ┆ 2021-12-16 03:00:00 ┆ [6] │ │ b ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ [3, 4] │ │ b ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 02:00:00 ┆ [4] │ └────────┴─────────────────────┴─────────────────────┴─────────────────────┴───────────┘Динамическая группировка по столбцу индекса
>>> lf = pl.LazyFrame( ... { ... "idx": pl.int_range(0, 6, eager=True), ... "A": ["A", "A", "B", "B", "B", "C"], ... } ... ) >>> lf.group_by_dynamic( ... "idx", ... every="2i", ... period="3i", ... include_boundaries=True, ... closed="right", ... ).agg(pl.col("A").alias("A_agg_list")).collect() shape: (4, 4) ┌─────────────────┬─────────────────┬─────┬─────────────────┐ │ _lower_boundary ┆ _upper_boundary ┆ idx ┆ A_agg_list │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ i64 ┆ i64 ┆ list[str] │ ╞═════════════════╪═════════════════╪═════╪═════════════════╡ │ -2 ┆ 1 ┆ -2 ┆ ["A", "A"] │ │ 0 ┆ 3 ┆ 0 ┆ ["A", "B", "B"] │ │ 2 ┆ 5 ┆ 2 ┆ ["B", "B", "C"] │ │ 4 ┆ 7 ┆ 4 ┆ ["C"] │ └─────────────────┴─────────────────┴─────┴─────────────────┘
LazyFrame.group_by_dynamic(
index_column: IntoExpr,
*,
every: str | timedelta,
period: str | timedelta | None = None,
offset: str | timedelta | None = None,
include_boundaries: bool = False,
closed: ClosedInterval = 'left',
label: Label = 'left',
group_by: IntoExpr | Iterable[IntoExpr] | None = None,
start_by: StartBy = 'window',
) → LazyGroupBy
© 2020 Ritchie Vink
© 2022 Polars contributors
Licensed under the MIT License.
https://docs.pola.rs/api/python/stable/reference/lazyframe/api/polars.LazyFrame.group_by_dynamic.html