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

如何在Vega中平滑连接Actual与Forecast折线?

在Vega中实现Actual与Forecast折线平滑连接的方法

当前代码中两条折线断开的核心原因是:Actual折线到C点后无后续数据,Forecast折线从D点开始,缺少C点的衔接数据,导致两段折线之间没有连续的点支撑连线。以下是两种可行的解决方案:


方法一:通过数据变换自动补全连接点

利用Vega的数据变换功能,自动提取Actual的最后一个点并合并到Forecast数据集中,让Forecast折线从Actual终点开始绘制。

修改后的完整代码:

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 400,
  "height": 200,
  "padding": 5,

  "data": [
    {
      "name": "table",
      "values": [
        {"x": "A", "y": 28, "type":"Actual"},
        {"x": "B", "y": 55, "type":"Actual"},
        {"x": "C", "y": 43, "type":"Actual"},
        {"x": "D", "y": 91, "type":"Forecast"},
        {"x": "E", "y": 81, "type":"Forecast"},
        {"x": "F", "y": 53, "type":"Forecast"},
        {"x": "G", "y": 19, "type":"Forecast"},
        {"x": "H", "y": 87, "type":"Forecast"},
        {"x": "I", "y": 52, "type":"Forecast"},
        {"x": "J", "y": 48, "type":"Forecast"}
      ]
    },
    {
      "name": "forecast_connected",
      "source": "table",
      "transform": [
        // 过滤出所有Forecast数据
        {"type": "filter", "expr": "datum.type === 'Forecast'"},
        // 合并Actual的最后一条数据
        {"type": "union", "tables": [
          {
            "data": "table",
            "transform": [
              {"type": "filter", "expr": "datum.type === 'Actual'"},
              // 按x排序后取最后一条Actual数据
              {"type": "window", "ops": ["row_number"], "as": ["row"], "sort": [{"field": "x"}]},
              {"type": "filter", "expr": "datum.row === max('row')"}
            ]
          }
        ]},
        // 按x轴顺序排序,确保折线连接正确
        {"type": "sort", "field": "x"}
      ]
    }
  ],

  "scales": [
    {
      "name": "x",
      "type": "band",
      "range": "width",
      "domain": {"data": "table", "field": "x"}
    },
    {
      "name": "y",
      "type": "linear",
      "range": "height",
      "nice": true,
      "zero": true,
      "domain": {"data": "table", "field": "y"}
    }
  ],

  "axes": [
    {"orient": "bottom", "scale": "x"},
    {"orient": "left", "scale": "y"}
  ],

  "marks": [
    {
      "type": "line",
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "x"},
          "y": {"scale":"y","field": "y"},
          "stroke": {"value": "black"},
          "strokeWidth": {"value": 2}
        },
        // 只显示Actual类型的点
        "update": {"opacity": {"expr": "datum.type === 'Actual' ? 1 : 0"}}
      }
    },
    {
      "type": "line",
      "from": {"data": "forecast_connected"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "x"},
          "y": {"scale":"y","field": "y"},
          "stroke": {"value": "gray"},
          "strokeWidth": {"value": 2},
          "strokeDash": {"value": [3,5]}
        }
      }
    }
  ]
}

方法二:手动补充数据源(简单直接)

如果数据量小且固定,可直接在数据源中添加一个衔接点:复制Actual的最后一条记录,将类型改为Forecast,让Forecast折线自然连接到Actual终点。

修改后的数据部分:

"data": [
  {
    "name": "table",
    "values": [
      {"x": "A", "y": 28, "type":"Actual"},
      {"x": "B", "y": 55, "type":"Actual"},
      {"x": "C", "y": 43, "type":"Actual"},
      {"x": "C", "y": 43, "type":"Forecast"}, // 新增连接点
      {"x": "D", "y": 91, "type":"Forecast"},
      {"x": "E", "y": 81, "type":"Forecast"},
      {"x": "F", "y": 53, "type":"Forecast"},
      {"x": "G", "y": 19, "type":"Forecast"},
      {"x": "H", "y": 87, "type":"Forecast"},
      {"x": "I", "y": 52, "type":"Forecast"},
      {"x": "J", "y": 48, "type":"Forecast"}
    ]
  }
]

保留原marks中的折线定义即可,Forecast折线会自动从C点连接到D点。


核心原理

折线的绘制依赖连续的数据点,只要让其中一段折线包含另一段的终点数据,就能在两个分段之间形成自然的平滑连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:14:57