Open
Description
Is your feature request related to a problem?
Add syntactic sugar for rolling aggregation.
What is the motivation behind your request?
Polars (and pandas) support DataFrame.rolling()
. For example:
import polars as pl
(
pl.scan_parquet("assets.parquet")
.filter(pl.col("symbol").is_in * (["ABBV", "XOM"]))
.with_columns(price_rolling=pl.col("price").rolling_mean(2).over("symbol"))
.collect()
)
The desired NULL behavior makes this more involved in Ibis (or SQL):
import ibis
from ibis import _
w = ibis.window(group_by="symbol", order_by="date", preceding=1, following=0)
ibis.read_parquet("assets.parquet").filter(_.symbol.isin(["ABBV", "XOM"])).mutate(
price_rolling=ibis.ifelse(
_.price.count().over(w) >= 2, _.price.mean().over(w), None
)
)
Motivated by discussion of https://www.linkedin.com/posts/marcogorelli_rolling-mean-polars-vs-duckdb-syntax-activity-7261736840561397761-LYLh/ with @MarcoGorelli.
Describe the solution you'd like
import ibis
from ibis import _
w = ibis.window(group_by="symbol", order_by="date", preceding=1, following=0)
ibis.read_parquet("assets.parquet").filter(_.symbol.isin(["ABBV", "XOM"])).mutate(
price_rolling=_.price.rolling_mean().over(w), None
)
or
import ibis
from ibis import _
w = ibis.rolling(group_by="symbol", order_by="date", preceding=1, following=0)
ibis.read_parquet("assets.parquet").filter(_.symbol.isin(["ABBV", "XOM"])).mutate(
price_rolling=_.price.mean().over(w), None
)
or even
import ibis
from ibis import _
(
ibis.read_parquet("assets.parquet")
.filter(_.symbol.isin(["ABBV", "XOM"]))
.group_by("symbol")
.order_by("date")
.mutate(price_rolling=_.price.rolling_mean(2))
)
What version of ibis are you running?
9.5.0
What backend(s) are you using, if any?
DuckDB
Code of Conduct
- I agree to follow this project's Code of Conduct
Metadata
Metadata
Assignees
Type
Projects
Status
backlog