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

如何在Vega-Lite中用Window Lag处理缺失月度数据实现同比对比?

Vega-Lite月度同比(YoY)对比的缺失数据处理方案

问题背景

使用Vega-Lite构建月度数据同比对比图表时,当前配置依赖window变换的lag:12实现去年同月数据关联,但当存在缺失月度数据时,该方法因假设数据连续有序,会导致同比匹配错误或失效。核心疑问:

  • 是否能让Vega-Lite智能对齐当前月份与去年同月的数据(即使中间缺月)?
  • 是否可纯通过Vega-Lite的变换/插补功能解决?
  • 是否必须外部预处理补全所有月份?

解决方案

1. 智能对齐的可行性

完全可以实现基于年份+月份的精确匹配,无需依赖连续的月度数据序列,直接关联对应去年同月的数值。

2. 纯Vega-Lite实现方案

无需补全缺失月份,通过计算年份月份标识+lookup变换实现精准同比关联,替代原有的lag方法。核心思路是:

  • 对每个月度数据生成统一的year_month标识(如"2024-01")
  • 计算去年同月的标识yoy_year_month(如"2023-01")
  • 用lookup变换根据标识匹配去年同月的聚合值

修改后的完整配置如下:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "layer": [
    {
      "data": {
        "format": {"parse": {"date": "date:%Y-%m-%d"}},
        "values": [
          {"date": "2024-01-18", "daily_total_login": 497},
          {"date": "2024-02-18", "daily_total_login": 296},
          {"date": "2024-03-18", "daily_total_login": 325},
          {"date": "2024-04-18", "daily_total_login": 431},
          {"date": "2024-05-18", "daily_total_login": 401},
          {"date": "2024-06-17", "daily_total_login": 289},
          {"date": "2024-07-17", "daily_total_login": 236},
          {"date": "2024-08-17", "daily_total_login": 503},
          {"date": "2024-09-17", "daily_total_login": 296},
          {"date": "2024-10-17", "daily_total_login": 543},
          {"date": "2024-11-16", "daily_total_login": 208},
          {"date": "2024-12-16", "daily_total_login": 310},
          {"date": "2025-01-16", "daily_total_login": 550},
          {"date": "2025-02-11", "daily_total_login": 20},
          {"date": "2025-03-11", "daily_total_login": 31},
          {"date": "2025-04-11", "daily_total_login": 17},
          {"date": "2025-05-11", "daily_total_login": 10},
          {"date": "2025-06-11", "daily_total_login": 19},
          {"date": "2025-07-11", "daily_total_login": 16},
          {"date": "2025-08-11", "daily_total_login": 15},
          {"date": "2025-09-12", "daily_total_login": 10},
          {"date": "2025-10-13", "daily_total_login": 4},
          {"date": "2025-11-14", "daily_total_login": 23},
          {"date": "2025-12-29", "daily_total_login": 71}
        ]
      },
      "encoding": {
        "x": {
          "field": "year_month",
          "type": "ordinal",
          "scale": {"padding": 0.2},
          "title": "月份"
        }
      },
      "transform": [
        // 转换为日期对象并统一到当月第一天
        {"calculate": "toDate(datum.date)", "as": "date"},
        {"calculate": "datetime(year(datum.date), month(datum.date), 1)", "as": "date"},
        // 按月份聚合登录总量
        {
          "aggregate": [{"op": "sum", "field": "daily_total_login", "as": "sum_daily_login"}],
          "groupby": ["date"]
        },
        // 生成年份-月份标识(用于匹配)
        {"calculate": "timeFormat(datum.date, '%Y-%m')", "as": "year_month"},
        // 生成去年同月的标识
        {"calculate": (year(datum.date) - 1) + '-' + pad(month(datum.date) + 1, 2), "as": "yoy_year_month"},
        // 基于标识lookup去年同月的聚合值
        {
          "lookup": "yoy_year_month",
          "from": {
            "data": {"values": []},
            "key": "year_month",
            "fields": ["sum_daily_login"]
          },
          "as": "yoy_sum_daily_login"
        },
        // 过滤仅显示2025年数据
        {"filter": "year(datum.date) === 2025"}
      ],
      "layer": [
        {
          "mark": {"type": "line", "tooltip": true, "point": {"filled": false, "fill": "white"}, "color": "#1f77b4"},
          "encoding": {"y": {"field": "sum_daily_login", "type": "quantitative", "title": "登录总量"}}
        },
        {
          "mark": {"type": "line", "tooltip": true, "point": {"filled": false, "fill": "white"}, "color": "#ff7f0e"},
          "encoding": {"y": {"field": "yoy_sum_daily_login", "type": "quantitative", "title": "去年同月登录总量"}}
        }
      ]
    }
  ],
  "height": "container",
  "width": "container"
}

关键变换说明

  • 年份月份标识:通过timeFormat或直接计算生成%Y-%m格式的字符串,确保每个月份有唯一且可匹配的标识。
  • Lookup变换:基于标识精确匹配去年同月的聚合值,不受中间缺失月份影响——即使某月份没有数据,lookup会返回null,不会出现错位。
  • 无需补全数据:不需要插入空值或零值的月份,仅处理已有数据,图表会自动按现有月份的year_month有序展示。

3. 外部预处理的必要性

外部预处理(如Python/JS补全月份)不是必须的,但在以下场景可考虑:

  • 需要在图表中显示所有月份(包括无数据的月份,用零或空值占位)
  • 数据量极大,Vega-Lite的lookup变换性能不足
  • 需要复杂的插补逻辑(如按趋势填充缺失值)

如果仅需实现同比数据对齐,纯Vega-Lite方案足够简洁高效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:44:53