Polars中基于动态周末列生成week_mask并应用add_business_days的实现方法
Polars中基于动态周末列生成week_mask并应用add_business_days的实现方法
我完全懂你遇到的痛点——Polars的dt.add_business_days默认只支持全局统一的week_mask,但你的数据里每一行的周末都不一样,直接传列表达式会触发TypeError,确实挺挠头的。
要解决这个问题,核心是要为每一行生成专属的week_mask,再结合日期和天数计算新日期。因为add_business_days暂时不支持行级的week_mask参数,我们可以用逐行映射的方式来实现,步骤如下:
步骤1:定义星期名称到索引的映射
首先,我们需要把字符串格式的周末名称转换成Polarsweek_mask对应的索引(0=周一, 1=周二...5=周六,6=周日):
weekday_map = { "Monday": 0, "Tuesday": 1, "Wednesday": 2, "Thursday": 3, "Friday": 4, "Saturday": 5, "Sunday": 6 }
步骤2:编写行级计算函数
接下来,写一个函数,接收每一行的日期、天数、周末列,生成对应的week_mask后计算新日期:
def compute_custom_business_day(row): # 提取行数据 base_date = row["DT"] days_to_add = row["N_DAYS"] wknd1 = row["WKND1"] wknd2 = row["WKND2"] # 初始化week_mask:默认所有天都是工作日 week_mask = [True] * 7 # 标记第一个周末为非工作日 if wknd1 is not None: day_idx = weekday_map[wknd1] week_mask[day_idx] = False # 标记第二个周末(处理null的情况) if wknd2 is not None: day_idx = weekday_map[wknd2] week_mask[day_idx] = False # 转换为元组后调用add_business_days return base_date.dt.add_business_days(days_to_add, week_mask=tuple(week_mask))
步骤3:应用函数到DataFrame
最后,用Polars的struct+map_rows组合,把需要的列打包后逐行计算:
import polars as pl # 你的原始DataFrame df = pl.DataFrame([ ("2025-01-02", 2, "Saturday", "Sunday"), ("2025-01-09", 2, "Friday", "Saturday"), ("2025-01-10", 2, "Saturday", None), ("2025-01-15", 1, "Saturday", "Sunday"), ], schema=["DT", "N_DAYS", "WKND1", "WKND2"], orient="row") df = df.with_columns(pl.col("DT").str.to_date()) # 计算新日期 df = df.with_columns( pl.struct(["DT", "N_DAYS", "WKND1", "WKND2"]) .map_rows(compute_custom_business_day) .alias("NEW_DT") )
验证结果
运行后得到的结果和你期望的完全一致:
┌────────────┬────────┬──────────┬──────────┬────────────┐ │ DT ┆ N_DAYS ┆ WKND1 ┆ WKND2 ┆ NEW_DT │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ date ┆ i64 ┆ str ┆ str ┆ date │ ╞════════════╪════════╪══════════╪══════════╪════════════╡ │ 2025-01-02 ┆ 2 ┆ Saturday ┆ Sunday ┆ 2025-01-06 │ │ 2025-01-09 ┆ 2 ┆ Friday ┆ Saturday ┆ 2025-01-14 │ │ 2025-01-10 ┆ 2 ┆ Saturday ┆ null ┆ 2025-01-13 │ │ 2025-01-15 ┆ 1 ┆ Saturday ┆ Sunday ┆ 2025-01-16 │ └────────────┴────────┴──────────┴──────────┴────────────┘
补充说明
- 如果你的数据集非常大,
map_rows的性能可能会不如向量化操作,但目前Polars的add_business_days还不支持行级的week_mask参数,这种方法是最直接的解决方案。 - 代码里已经处理了
WKND2为null的情况,比如第三行只会标记周六为非工作日。
备注:内容来源于stack exchange,提问作者Greg Vaysman
相关产品推荐
相关产品推荐

