You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySpark含缺失周的时间序列滚动平均高效计算方案咨询

最优解决方案:用PySpark范围窗口函数避免补全缺失数据

你的痛点我完全理解——在大数据量下补全缺失周会显著增加数据体积,拖慢计算性能。其实我们可以不用显式补全任何数据,直接通过范围窗口函数来实现需求,性能会高效很多。

核心思路

因为缺失周的销量默认是0,我们只需要计算当前周及往前2周范围内的销量总和,再除以3即可得到3周滚动平均。这里的关键是用rangeBetween而非rowsBetween,因为我们要基于周编号的数值范围来确定窗口,而不是基于数据行的位置(毕竟缺失周没有对应的行)。

具体实现步骤

假设你的原始DataFrame名为df,包含wk_id(字符串类型,如201801)和sellout列:

  1. 将周编号转换为整数
    先把wk_id转成整数类型,这样才能正确计算范围:

    from pyspark.sql import functions as F
    from pyspark.sql.window import Window
    
    df = df.withColumn("wk_id_int", F.col("wk_id").cast("int"))
    
  2. 定义范围窗口
    如果你的数据是按品类等维度分组的,记得加上partitionBy(比如partitionBy("product_id"))。窗口范围设置为当前周往前推2周(rangeBetween(-2, 0)):

    # 全局窗口(如果无分组维度)
    window_spec = Window.orderBy("wk_id_int").rangeBetween(-2, 0)
    
    # 带分组的窗口(如有品类等维度)
    # window_spec = Window.partitionBy("product_id").orderBy("wk_id_int").rangeBetween(-2, 0)
    
  3. 计算3周滚动平均
    对窗口内的sellout求和后除以3,并用round保留3位小数:

    result_df = df.withColumn(
        "moving_avg_3w",
        F.round(F.sum("sellout").over(window_spec) / 3, 3)
    )
    

验证结果

运行上面的代码后,得到的结果和你的预期完全一致:

wk_idselloutmoving_avg_3w
2018011.00.333
2018025.02.000
2018033.03.000
2018051.01.333
2018065.02.000

为什么这个方案更优?

  • 无需补全数据:不会生成额外的缺失行,避免了大数据量下的数据膨胀问题。
  • 性能高效:窗口函数是PySpark的优化算子,执行效率远高于补全后再计算滚动平均。
  • 逻辑简洁:直接基于周编号的范围计算,逻辑清晰易懂,维护成本低。

注意事项

  • 确保wk_id是连续的周编号格式(如YYYYWW),这样rangeBetween(-2, 0)才能正确覆盖前2周到当前周的范围。如果你的周编号是其他格式(比如日期字符串),需要先转换为对应的周数再计算。
  • 如果wk_id原本就是整数类型,可以跳过第一步的类型转换。

内容的提问来源于stack exchange,提问作者pexmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:05:05