Search code examples
vega-lite

How to make a simple Waffle chart with Actual and Target colors in vega-lite?


How to make a simple waffle chart with actual and target colors in vega-lite? I want a different color for actual and target. If actual exceeds target then target should not show.


Solution

  • Like this. Inspired by Davide Bacci's great work.

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "datasets": {"source": [{"Target": "65", "Actual": "45"}]},
      "transform": [
        {"calculate": "sequence(1,101)", "as": "Sequence"},
        {"flatten": ["Sequence"]},
        {
          "calculate": "datum.Sequence <= datum.Actual ? 'A' : (datum.Sequence <= datum.Target ? 'B' : 'C')",
          "as": "Plot"
        },
        {"calculate": "ceil (datum.Sequence / 10)", "as": "row"},
        {"calculate": "datum.Sequence - datum.row * 10", "as": "col"}
      ],
      "layer": [
        {
          "mark": {
            "type": "circle",
            "filled": true,
            "tooltip": true,
            "stroke": "#9e9b9b",
            "strokeWidth": 0.7
          },
          "encoding": {
            "x": {"field": "col", "type": "ordinal", "axis": null},
            "y": {"field": "row", "type": "ordinal", "axis": null, "sort": "-y"},
            "color": {
              "field": "Plot",
              "type": "nominal",
              "legend": null,
              "condition": [
                {"test": "datum.Plot === 'A'", "value": "#27AE60"},
                {"test": "datum.Plot === 'B'", "value": "#F4D03F"},
                {"test": "datum.Plot === 'C'", "value": "#E5E7E9"}
              ]
            },
            "size": {"value": 241},
            "tooltip": [{"field": "Plot", "type": "nominal", "title": "Status"}]
          }
        },
        {
          "mark": {"type": "text", "fontSize": 12},
          "encoding": {
            "y": {"value": -15},
            "text": {
              "condition": {
                "test": "datum.Sequence == 1",
                "value": {
                  "expr": "'Target: ' + datum.Target + '%' + '   ' + 'Actual: ' + datum.Actual + '%'"
                }
              }
            }
          }
        }
      ],
      "config": {"view": {"stroke": "transparent"}}
    }
    

    Here is a square version also. The square version is great if you want set a different width and height.

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "width": 200,
      "height": 200,
      "datasets": {"source": [{"Target": "65", "Actual": "45"}]},
      "transform": [
        {"calculate": "sequence(1,101)", "as": "Sequence"},
        {"flatten": ["Sequence"]},
        {
          "calculate": "datum.Sequence <= datum.Actual ? 'Completed' : (datum.Sequence <= datum.Target ? 'Target' : 'Remaining')",
          "as": "Plot"
        },
        {"calculate": "ceil (datum.Sequence / 10)", "as": "row"},
        {"calculate": "datum.Sequence - datum.row * 10", "as": "col"}
      ],
      "layer": [
        {
          "mark": {
            "type": "rect",
            "filled": true,
            "tooltip": true,
            "stroke": "#fff",
            "strokeWidth": 1
          },
          "encoding": {
            "x": {"field": "col", "type": "ordinal", "axis": null},
            "y": {"field": "row", "type": "ordinal", "axis": null, "sort": "-y"},
            "color": {
              "field": "Plot",
              "type": "nominal",
              "legend": null,
              "condition": [
                {"test": "datum.Plot === 'Completed'", "value": "#27AE60"},
                {"test": "datum.Plot === 'Target'", "value": "#F4D03F"},
                {"test": "datum.Plot === 'Remaining'", "value": "#E5E7E9"}
              ]
            },
            "tooltip": [{"field": "Plot", "type": "nominal", "title": "Status"}]
          }
        },
        {
          "mark": {"type": "text", "fontSize": 12},
          "encoding": {
            "y": {"value": -15},
            "text": {
              "condition": {
                "test": "datum.Sequence == 1",
                "value": {
                  "expr": "'Target: ' + datum.Target + '%' + '  ' + 'Actual: ' + datum.Actual + '%'"
                }
              }
            }
          }
        }
      ],
      "config": {"view": {"stroke": "transparent"}, "background": "#fff"}
    }