Скажем, у меня есть:
data = {
'id': ['a', 'a', 'a', 'b', 'b', 'b', 'b'],
'd': [1,2,3,0,1,2,3],
'sales': [5,1,3,4,1,2,3],
}
Я хотел бы добавить столбец со скользящим средним с размером окна 2, с min_periods=2
, более 'id'
В Polars я могу:
import polars as pl
df = pl.DataFrame(data)
df.with_columns(sales_rolling = pl.col('sales').rolling_mean(2).over('id'))
shape: (7, 4)
┌─────┬─────┬───────┬───────────────┐
│ id ┆ d ┆ sales ┆ sales_rolling │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i64 ┆ i64 ┆ f64 │
╞═════╪═════╪═══════╪═══════════════╡
│ a ┆ 1 ┆ 5 ┆ null │
│ a ┆ 2 ┆ 1 ┆ 3.0 │
│ a ┆ 3 ┆ 3 ┆ 2.0 │
│ b ┆ 0 ┆ 4 ┆ null │
│ b ┆ 1 ┆ 1 ┆ 2.5 │
│ b ┆ 2 ┆ 2 ┆ 1.5 │
│ b ┆ 3 ┆ 3 ┆ 2.5 │
└─────┴─────┴───────┴───────────────┘
Что такое эквивалент DuckDB? я пробовал
import duckdb
duckdb.sql("""
select
*,
mean(sales) over (
partition by id
order by d
range between 1 preceding and 0 following
) as sales_rolling
from df
""").sort('id', 'd')
но получить
┌─────────┬───────┬───────┬───────────────┐
│ id │ d │ sales │ sales_rolling │
│ varchar │ int64 │ int64 │ double │
├─────────┼───────┼───────┼───────────────┤
│ a │ 1 │ 5 │ 5.0 │
│ a │ 2 │ 1 │ 3.0 │
│ a │ 3 │ 3 │ 2.0 │
│ b │ 0 │ 4 │ 4.0 │
│ b │ 1 │ 1 │ 2.5 │
│ b │ 2 │ 2 │ 1.5 │
│ b │ 3 │ 3 │ 2.5 │
└─────────┴───────┴───────┴───────────────┘
Это очень близко, но Duckdb по-прежнему вычисляет скользящее среднее, даже если в окне имеется только одно значение. Как я могу воспроизвести поведение min_periods=2
(по умолчанию) из Polars?
🤔 А знаете ли вы, что...
В Python есть среды разработки, такие как Jupyter Notebook, которые упрощают работу с данными и исследованиями.
Вы можете использовать оператор падеж и счетчик:
duckdb.sql("""
from df
select
*,
case
when count(*) over rolling2 = 2 then
mean(sales) over rolling2
end as sales_rolling
window rolling2 as (
partition by id
order by d
rows between 1 preceding and current row
)
""").sort('id', 'd')
┌─────────┬───────┬───────┬───────────────┐
│ id │ d │ sales │ sales_rolling │
│ varchar │ int64 │ int64 │ double │
├─────────┼───────┼───────┼───────────────┤
│ a │ 1 │ 5 │ NULL │
│ a │ 2 │ 1 │ 3.0 │
│ a │ 3 │ 3 │ 2.0 │
│ b │ 0 │ 4 │ NULL │
│ b │ 1 │ 1 │ 2.5 │
│ b │ 2 │ 2 │ 1.5 │
│ b │ 3 │ 3 │ 2.5 │
└─────────┴───────┴───────┴───────────────┘
Обратите внимание, что здесь я использовал именованное окно и обрамление строк.