Search code examples
powerbivega-litedeneb

creating a symmetry shading with vega-lite (vega) similar to the scatter chart of Power BI


I'm wondering if someone can guide to an idea, the algorithm, an example of how to create Power BI's symmetry shading for scatter charts (https://learn.microsoft.com/en-us/power-bi/visuals/power-bi-visualization-scatter?tabs=powerbi-desktop#add-analytics-to-your-chart)

This

{
  "width": 600,
  "height": 600,
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {"ID": "I", "xVal": 3, "yVal": 2},
      {"ID": "I", "xVal": 4, "yVal": 6},
      {"ID": "II", "xVal": 3, "yVal": 3}
    ]
  },
  "mark": {
    "type": "circle"
  },
  "encoding": {
    "x": {
      "field": "xVal", "type":"quantitative",
      "scale": {"domain": [0, 7]}
    },
    "y": {
      "field": "yVal", "type":"quantitative",
      "scale": {"domain": [0, 7]}
    }
  }
}

can looks like this enter image description here in Power BI, with the feature symmetry shading enabled.

I'm interested in how to draw the "shapes", being more precise, and getting/creating the coordinates of the shapes.

Any ideas?


Solution

  • I came up with a slightly different solution, there is a background rect based on the data, then there is a regression line and also an area chart. I use the linear interpolation for the area chart and also the regression transform. I'm sure that this could be done more simply, but I'm happy now :-) The scatter chart looks like this: enter image description here

    the code that works in the vega-lite editor:

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "width": 600,
      "height": 600,
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "data": {
        "values": [
          {"ID": "I", "xVal": 125, "yVal": 55, "size": 80},
          {"ID": "II", "xVal": 673, "yVal": 297, "size": 30},
          {"ID": "III", "xVal": 500, "yVal": 160, "size": 50}
        ]
      },
      "transform":[
        {
          "joinaggregate": [
              {"op": "max", "field": "yVal", "as": "maxyVal"},
              {"op": "min", "field": "yVal", "as": "minyVal"},
              {"op": "max", "field": "xVal", "as": "maxxVal"},
              {"op": "min", "field": "xVal", "as": "minxVal"}
            ]
        }
      ],
      "params": [
        {"name": "maxY", "expr": "data('data_0')[0]['maxyVal'] "},
        {"name": "minY", "expr": "data('data_0')[0]['minyVal'] "},
        {"name": "maxX", "expr": "data('data_0')[0]['maxxVal'] "},
        {"name": "minX", "expr": "data('data_0')[0]['minxVal']  "}
      ],
      "title": "Power BIs Symmetry Shading and the Ratio Line now in Deneb",
      "layer": [
            { "description": "the area left/above",
            "mark": {
              "type":"rect",
              "color": "lightgray",
              "tooltip": {"content": "data" }
            },
            "encoding": {
              "x": {
                "datum": {"expr": "minX"},
                "type": "quantitative",
                "scale": {"domain": {"expr": "[0, maxX]"}}
              },
              "y": {
                "datum": {"expr": "0"},
                "type": "quantitative",
                "scale": {"domain": {"expr": "[0, maxY]"}}
              },
              "x2": {"datum": {"expr": "maxX"}},
              "y2": {"datum": {"expr": "maxY"}}
            }  
          },
    
            { "description": "the area below right/below",
              "mark": {
              "type":"area",
              "interpolate": "linear",
              "color": "yellow",
              "tooltip": {"content": "data" }
            },
            "transform": [
                {
                  "regression": "yVal",
                  "on": "xVal"
                }
            ],
            "encoding": {
              "x": {
                "field": "xVal",
                "type": "quantitative",
                "scale": {"domain": {"expr": "[0, maxX]"}}
              },
              "y": {
                "field": "yVal",
                "type": "quantitative",
                "scale": {"domain": {"expr": "[0, maxY]"}}
              }
            }  
            },
            { "description": "the  regression line",
              "mark": {
                "type": "line",
                "color": "firebrick",
                "opacity": 0.4
              },
              "transform": [
                {
                  "regression": "yVal",
                  "on": "xVal"
                }
              ],
              "encoding": {
                "x": {
                  "field": "xVal",
                  "type": "quantitative",
                  "scale": {"domain": {"expr": "[0, maxX]"}}
                },
                "y": {
                  "field": "yVal",
                  "type": "quantitative",
                  "scale": {"domain": {"expr": "[0, maxY]"}}
                }
              }
            },
            { "description": "the ALL bubble",
              "mark": {
                "type":"circle",
                "opacity": 0.2,
                "color":"blue",
                "tooltip": {"content": "data"}
              },
              "encoding": {
                "x": {"aggregate":"mean", "field": "xVal","scale": {"domain": {"expr": "[0, maxX]"}}},
                "y": {"aggregate":"mean", "field": "yVal", "scale": {"domain": {"expr": "[0, maxY]"}}},
                "size": {
                  "aggregate":"sum", 
                  "field":"size", 
                  "legend": null
                }
              }
            },
            { "description": "all the bubbles",
              "mark": {
                "type":"circle",
                "opacity": 0.4,
                "tooltip": true
              },
              "encoding": {
                "x": {"field":"xVal", "type": "quantitative", "scale": {"domain": {"expr": "[0, minX]"}},
                "axis": {"title": null, "grid":false}},
                "y": {"field": "yVal", "type": "quantitative", "scale": {"domain": {"expr": "[0, maxY]"}},
                "axis": {"title": null, "grid":false}},
                "size": {
                  "field":"size", 
                  "type": "quantitative",
                  "scale": {"rangeMax": 50000}
                },
                "color": {"field":"ID", "legend": null}
              }
            }           
      ]
    }