Search code examples
powerbipowerbi-desktopvega-litepowerbi-custom-visualsdeneb

Vega-Lite (Deneb): Is it possible to create a jittered plot inside a bar/column chart?


- Requirement: Jittered Plot inside a column/bar chart in Vega-Lite (Deneb) for Power BI

Challenges:

I wish to reproduce the desired output below. I am unsure how to best approach this, and I'm doubley unsure as to how best to prepare the underlying data. I think the solution may lie in using the Vega expression "random()" for the jitter, but then I'm stuck when it comes to distributing the dots across the axis. I've seen examples of "xOffset" and "yOffset" in the encoding, but I'm not able to replicate. I've also considered using the data generator for "sequence" to create a dot for each item sold but failed at this also. In summary, my requirement is:

  • creating a jitter plot which creates a dot mark for each invidual item sold
  • randomising the dots across the x & y axis of each bar so they are distrubuted within the range of the bar's revenue sold value
  • (bonus challenge: highlighting the category and axis label of the best-selling product)

Desired Output:

Desired Output

Data-provided:

I've made several attemps but I'm not able to figure how the best approach, so I've prepared the PBIX File with Data in the following ways:

  • Data transformed in PowerQuery (each row is an item sold)
  • Raw Data in summarised table
  • Raw Data as In-line dataset in Deneb

pbix exa

Link to PBIX and Examples

Any help and guidance is muchly appreciated. Thank you.


Solution

  • Closest I can get with VL:

    enter image description here

    Add OrderID to your field well and make sure don't summarise is set.

    enter image description here

    {
      "data": {"name": "dataset"},
      "height": {"step": 35},
      "transform": [
        {
          "joinaggregate": [
            {
              "op": "sum",
              "field": "Total_Revenue",
              "as": "Total"
            }
          ],
          "groupby": ["Product"]
        },
        {
          "calculate": "random()*datum.Total",
          "as": "jitterX"
        },
           {
          "calculate": "random()",
          "as": "jitterY"
        }
      ],
      "encoding": {
        "y": {
          "field": "Product",
          "type": "nominal"
        },
        "x": {
          "field": "Total_Revenue",
          "type": "quantitative"
        }
      },
      "layer": [
        {
          "mark": {
            "type": "bar",
            "stroke": "black",
            "strokeWidth": 0.5,
            "fill": "#fae19b"
          },
          "encoding": {
            "x": {
              "field": "Total_Revenue",
              "type": "quantitative",
              "aggregate": "sum"
            }
          }
        },
        {
          "mark": {
            "type": "circle",
            "fill": "#c61d10",
            "opacity": 0.8, "size":10      },
          "encoding": {
            "x": {
              "field": "jitterX",
              "type": "quantitative"
            },
              "yOffset": {
              "field": "jitterY",
              "type": "quantitative", "scale": {"domain": [0, 2]}
            }
          }
        }
      ]
    }