Search code examples
powerbipowerbi-desktopvega-litevegadeneb

Deneb - scatterplot x & y sorted asc


I need to draw a scatterplot in DENEB (vega or vega lite). Basically I need to create a scatter plot where I will have x and y sorted ascending and plot against each other, ... so the number are not correlated to each other anymore

Please have a look at the attached image

scatterplot

I tried but I cant sore x and y in the same time. I guess I need to split this into two seperate lists, sort them and merge into one dataset???

{
  "data": {
    "values": [
      {"x": "1", "y": "3.2"},
      {"x": "2", "y": "1.9"},
      {"x": "4", "y": "2.1"},
      {"x": "3", "y": "4.5"},
      {"x": "6", "y": "5.1"},
      {"x": "5", "y": "8.5"},
      {"x": "7", "y": "6"},
      {"x": "8", "y": "7.9"},
      {"x": "9", "y": "9.1"},
      {"x": "10", "y": "11"}
    ]
  },
    "mark": {"type":"line",
    "point":true},
    "encoding": {
      "x": {"field": "x", "type": "quantitative"},
      "y": {"field": "y", "type": "quantitative"}
    }
}

Solution

  • Vega only solution.

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "background": "white",
      "padding": 5,
      "width": 200,
      "height": 200,
      "style": "cell",
      "data": [
        {
          "name": "source_0",
          "values": [
            {"x": 1, "y": 3.2},
            {"x": 2, "y": 1.9},
            {"x": 4, "y": 2.1},
            {"x": 3, "y": 4.5},
            {"x": 6, "y": 5.1},
            {"x": 5, "y": 8.5},
            {"x": 7, "y": 6},
            {"x": 8, "y": 7.9},
            {"x": 9, "y": 9.1},
            {"x": 10, "y": 11}
          ],
          "transform": [
            {
              "type": "window",
              "params": [null],
              "as": ["row"],
              "ops": ["row_number"],
              "fields": [null],
              "sort": {"field": [], "order": []}
            },
            {"type": "collect", "sort": {"field": "y"}}
          ]
        },
        {
          "name": "data_0",
          "source": "source_0",
          "transform": [
             {"type": "collect", "sort": {"field": "x"}},
            {"type": "formula", "expr": "pluck(data('source_0'),'y')[datum.row-1]", "as": "newY"}
          ]
        },
        {
          "name": "data_1",
          "source": "data_0",
          "transform": [
            {
              "type": "filter",
              "expr": "isValid(datum[\"x\"]) && isFinite(+datum[\"x\"]) && isValid(datum[\"y\"]) && isFinite(+datum[\"y\"])"
            }
          ]
        }
      ],
      "marks": [
        {
          "name": "layer_0_marks",
          "type": "line",
          "style": ["line"],
          "sort": {"field": "datum[\"x\"]"},
          "from": {"data": "data_0"},
          "encode": {
            "update": {
              "stroke": {"value": "#4c78a8"},
              "description": {
                "signal": "\"x: \" + (format(datum[\"x\"], \"\")) + \"; y: \" + (format(datum[\"y\"], \"\"))"
              },
              "x": {"scale": "x", "field": "x"},
              "y": {"scale": "y", "field": "newY"},
              "defined": {
                "signal": "isValid(datum[\"x\"]) && isFinite(+datum[\"x\"]) && isValid(datum[\"y\"]) && isFinite(+datum[\"y\"])"
              }
            }
          }
        },
        {
          "name": "layer_1_marks",
          "type": "symbol",
          "style": ["point"],
          "from": {"data": "data_1"},
          "encode": {
            "update": {
              "opacity": {"value": 1},
              "fill": {"value": "#4c78a8"},
              "ariaRoleDescription": {"value": "point"},
              "description": {
                "signal": "\"x: \" + (format(datum[\"x\"], \"\")) + \"; y: \" + (format(datum[\"y\"], \"\"))"
              },
              "x": {"scale": "x", "field": "x"},
              "y": {"scale": "y", "field": "newY"}
            }
          }
        }
      ],
      "scales": [
        {
          "name": "x",
          "type": "linear",
          "domain": {
            "fields": [
              {"data": "data_0", "field": "x"},
              {"data": "data_1", "field": "x"}
            ]
          },
          "range": [0, {"signal": "width"}],
          "nice": true,
          "zero": false
        },
        {
          "name": "y",
          "type": "linear",
          "domain": {
            "fields": [
              {"data": "data_0", "field": "y"},
              {"data": "data_1", "field": "y"}
            ]
          },
          "range": [{"signal": "height"}, 0],
          "nice": true,
          "zero": true
        }
      ],
      "axes": [
        {
          "scale": "x",
          "orient": "bottom",
          "gridScale": "y",
          "grid": true,
          "tickCount": {"signal": "ceil(width/40)"},
          "domain": false,
          "labels": false,
          "aria": false,
          "maxExtent": 0,
          "minExtent": 0,
          "ticks": false,
          "zindex": 0
        },
        {
          "scale": "y",
          "orient": "left",
          "gridScale": "x",
          "grid": true,
          "tickCount": {"signal": "ceil(height/40)"},
          "domain": false,
          "labels": false,
          "aria": false,
          "maxExtent": 0,
          "minExtent": 0,
          "ticks": false,
          "zindex": 0
        },
        {
          "scale": "x",
          "orient": "bottom",
          "grid": false,
          "title": "x",
          "labelFlush": true,
          "labelOverlap": true,
          "tickCount": {"signal": "ceil(width/40)"},
          "zindex": 0
        },
        {
          "scale": "y",
          "orient": "left",
          "grid": false,
          "title": "y",
          "labelOverlap": true,
          "tickCount": {"signal": "ceil(height/40)"},
          "zindex": 0
        }
      ]
    }