如何在Polars中实现基于日期范围的条件累计求和
问题分析
你原代码的问题在于:group_by('Date1') 后,agg 中的过滤逻辑是**在每个分组内部(即仅当前Date1对应的那一行)**判断条件,而不是让每个Date1和所有行的Date2/Date3做范围匹配,所以无法得到跨行的求和结果。
解决方案
要实现每个Date1匹配所有行的日期范围并求和,需要让每个Date1能访问到全表的Date2/Date3/Value数据,以下是两种可行方法:
方法1:交叉连接+过滤+分组求和
通过交叉连接生成所有Date1与全表行的组合,再过滤符合条件的行后求和,最后补全未匹配的Date1并填0:
import polars as pl result = ( # 取出所有Date1 testDf.select("Date1") # 与全表的日期范围和数值列做交叉连接 .cross_join(testDf.select("Date2", "Date3", "Value")) # 过滤Date1落在[Date2, Date3]范围内的行 .filter((pl.col("Date1") >= pl.col("Date2")) & (pl.col("Date1") <= pl.col("Date3"))) # 按Date1分组计算符合条件的Value总和 .group_by("Date1") .agg(pl.col("Value").sum().alias("Sum")) # 右连接原表的Date1,确保所有原始Date1都被保留 .right_join(testDf.select("Date1"), on="Date1") # 无匹配结果的Date1填充0 .fill_null(0) # 按Date1排序 .sort("Date1") ) print(result)
方法2:广播+窗口函数求和
利用broadcast()将单个Date1广播到全表行,结合窗口函数直接计算每个Date1的符合条件的总和:
import polars as pl result = ( testDf.with_columns( # 广播当前Date1到所有行,过滤符合范围的Value后求和,按Date1分组计算 pl.col("Value") .filter((pl.col("Date1").broadcast() >= pl.col("Date2")) & (pl.col("Date1").broadcast() <= pl.col("Date3"))) .sum() .over("Date1") .alias("Sum") ) # 只保留目标列 .select("Date1", "Sum") # 去重(每行的Sum值重复) .unique() # 无匹配结果的Date1填充0 .fill_null(0) # 按Date1排序 .sort("Date1") ) print(result)
验证结果
两种方法都会输出你预期的结果:
shape: (5, 2) ┌────────────┬─────┐ │ Date1 ┆ Sum │ │ --- ┆ --- │ │ date ┆ i64 │ ╞════════════╪═════╡ │ 2024-04-01 ┆ 0 │ │ 2024-04-06 ┆ 10 │ │ 2024-04-07 ┆ 25 │ │ 2024-04-10 ┆ -15 │ │ 2024-04-11 ┆ 5 │ └────────────┴─────┘
内容的提问来源于stack exchange,提问作者AColoredReptile
相关产品推荐
相关产品推荐

