Deneb: Lollipops

Hi!

I’ve recently been getting really excited by the inclusion of Vega / Vegalite visuals within Power BI thanks to the awesome Deneb visual. I’ve got a few projects on the go and I’ll be posting all the code for them here. I’m a beginner so my code is not that well formatted just yet, but I will update them as I go along.

For a kick off, a finance favourite, Lollipop charts. I wasn’t particularly taken with any of the offerings on AppSource, and I thought it should be a relatively simple starting point.

For anyone unsure, Lollipop charts are a great way to visualise variance across categories, either as an absolute figure, or a percentage to or from a target. For example, they are often used to show Year on Year changes.

Here is the vegalite to replicate this chart:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "Minimalist Lollipop chart with conditional colouring",
  "author": "Andy Murphy | Day to Data Stuff",
  "data": {"name": "dataset"},
  "layer": [
    {
      "description": "Lollipop Stick",
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "field": "Number",
          "type": "quantitative"
        },
        "y": {
          "field": "Category",
          "type": "ordinal"
        },
        "color": {
          "condition": {
            "test": "datum['Number']<0",
            "value": "Red"
          },
          "value": "Black"
        }
      }
    },
    {
      "description": "Lollipop",
      "mark": {
        "type": "point",
        "tooltip": true
      },
      "encoding": {
        "color": {
          "condition": {
            "test": "datum['Number']<0",
            "value": "Red"
          },
          "value": "Black"
        },
        "x": {
          "field": "Number",
          "type": "quantitative"
        },
        "y": {
          "field": "Category",
          "type": "ordinal"
        }
      }
    },
    {
      "description": "Value label",
      "mark": {
        "type": "text",
        "baseline": "top",
        "dy": -20
      },
      "encoding": {
        "color": {
          "condition": {
            "test": "datum['Number']<0",
            "value": "Red"
          },
          "value": "Black"
        },
        "x": {
          "field": "Number",
          "type": "quantitative"
        },
        "y": {
          "field": "Category",
          "type": "ordinal"
        },
        "text": {"field": "Number"}
      }
    },
    {
      "description": "0 Baseline",
      "mark": "line",
      "encoding": {
        "x": {"datum": 0},
        "y": {"field": "Category"}
      }
    }
  ]
}

As vegalite uses the JSON format, it doesn’t support commenting in the code.

Instead, I’ll just type some notes here alongside it.

So in this “data” step we bind our dataset. In Deneb, this is just whatever data you have put into your Deneb visual, so leave this alone.

Next we need to build a few different items to make this chart work, so all of our code is going in the “layer”:[] array.

“description” is the one bit of commenting vegalite supports, so it is good to use this to remind yourself what each bit does, as with multiple layers it can get a bit messy.

Ok, if you are stealing this code for your own visual, here’s the important bit - you need to replace all references to “Number” with whatever your numerical field it. Replace “Category” with whatever your categorical field is and you should be good to go.

Here is the conditional colouring bit, we are using a “test” to run a logical check on the value. Like a normal if statement, if the statement is true it will take the first value for the colour field (I resent being forced to spell color that way), so here we are just checking if the value is negative. If so it applies the first value, otherwise it takes the next one. I used Red and Black but you can swap these out for any colour - you can either name it or use a hexcode.

Note - I’ve just rewritten this across my layers, I’m sure there is a way to more neatly incorporate this into the styling config, but that is for version 2!

OK onto the second layer - the first one has plotted our lollipop sticks, now we just need to add the lollipop itself.

And then we add the labels

Bit more coloring magic

I’m sure there is a more efficient way to just set a common axis once too, but I couldn’t quite figure out the syntax for that - if anyone has a suggestion please let me know!

Last, I couldn’t think of an easier way to plot our “axis” line in the middle of the chart, because it’s actually halfway through the chart - my data runs from -6 to +7. Therefore I just plotted a line across all categories where x=0 by using the “datum” function, which serves as our faux-axis line.


OK so that is all the encoding done. Now we just need to flip to our Config tab in the Deneb visual and bash this in:

{
  "view": {"stroke": "transparent"},
  "font": "Segoe UI",
  "bar": {
    "color": "black",
    "height": {"band": 0.035}
  },
  "line": {
    "color": "gray",
    "strokeWidth": 0.5,
    "strokeCap": "round",
    "strokeJoin": "round"
  },
  "point": {
    "filled": true,
    "size": 125,
    "opacity": 1
  },
  "text": {
    "font": "Segoe UI",
    "fontSize": 12,
    "fill": "#605E5C"
  },
  "axis": {
    "domainDashOffset": 15,
    "labelColor": "#605E5C",
    "labelFontSize": 14,
    "titleFont": "Segoe UI",
    "titleColor": "#252423",
    "titleFontSize": 16,
    "titleFontWeight": "normal"
  },
  "axisX": {
    "labelPadding": 15,
    "domain": false,
    "grid": false,
    "labels": false,
    "header": false,
    "title": false,
    "ticks": false
  },
  "axisY": {
    "offset": 25,
    "title": false,
    "ticks": false,
    "grid": false,
    "domain": false
  }
}

In this code you can finetune all of the features. For me, this is what makes VegaLite so powerful. We all have clients with exacting demands for very specific formatting, so the ability to control almost everything in the visual is a gamechanger for Power BI! Anyway, if you are stealing this code, this is the part where you format it - I think most of the fields there are pretty self explanatory.

And that’s it - first Deneb visual done!

Also, huge respect to Daniel Marsh-Patrick for making the Deneb visual, it’s really awesome.

Finally, I’m enjoying playing around with Deneb so if you have a particular visual request you are trying to figure out, I’m looking for usecases! If you have an interesting problem let me know by emailing me the usecase, preferably with some sample data!

Next
Next

Deneb: Timeline with conditional markers