Drew Dara-Abrams
Drew Dara-Abrams

Reputation: 8054

label bar chart in Vega Lite with both absolute number and percentage

I am able to label a bar chart created in Vega Lite, with either its percentage of the total or its absolute number, like so:

enter image description here

And here's the spec:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "width": "container",
  "height": "container",
  "data": {
    "values": [
      {
        "binMin": -300,
        "binMax": 0,
        "binName": "-5 to 0 minutes",
        "count": 29,
        "percentOfTotal": 0.14215686274509803
      },
      {
        "binMin": 0,
        "binMax": 360,
        "binName": "0 to +6 minutes",
        "count": 51,
        "percentOfTotal": 0.25
      },
      {
        "binMin": 360,
        "binMax": 600,
        "binName": "+6 to +10 minutes",
        "count": 32,
        "percentOfTotal": 0.1568627450980392
      },
      {
        "binMin": 600,
        "binMax": 1200,
        "binName": "+10 to +20 minutes",
        "count": 90,
        "percentOfTotal": 0.4411764705882353
      }
    ]
  },
  "layer": [
    {"mark": "bar"},
    {
      "mark": {
        "type": "text",
        "align": "center",
        "yOffset": -10,
        "fontSize": 18
      },
      "encoding": {
        "text": {
          "field": "percentOfTotal",
          "type": "quantitative",
          "format": ".0%",
          "formatType": "number"
        }
      }
    }
  ],
  "encoding": {
    "x": {
      "field": "binName",
      "type": "nominal",
      "title": "Wait Time for Transfer (Minutes)",
      "axis": {"titleFontSize": 18, "labelAngle": 0, "labelFontSize": 14},
      "sort": {"field": "binMin"}
    },
    "y": {
      "field": "count",
      "type": "quantitative",
      "title": "Total Transfers",
      "axis": {"titleFontSize": 18, "labelFontSize": 14}
    },
    "color": {
      "legend": false,
      "field": "binMin",
      "scale": {"range": ["red", "orange", "green", "yellowgreen"]}
    }
  }
}

I would like to change the label to display both, like a label for the left/red bar of "29 (14%)".

I have figured out how to set config.customFormatTypes = true and to write a little formatter function in JavaScript. However, I am unclear how I would be able to pass two fields into this formatter, in order to pass it both the absolute number and the percentage (or the absolute number for that category and the total number across all categories).

Any pointers? Thanks.

Upvotes: 1

Views: 1807

Answers (1)

wahab memon
wahab memon

Reputation: 2416

To display the concatenated value of 2 fields "29 (14%)" over text you can use transform calculate and generate a concatenated string based on your field. Then, use that field in your text mark as done below or refer editor:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "width": "container",
  "height": "container",
  "data": {
    "values": [
      {
        "binMin": -300,
        "binMax": 0,
        "binName": "-5 to 0 minutes",
        "count": 29,
        "percentOfTotal": 0.14215686274509803
      },
      {
        "binMin": 0,
        "binMax": 360,
        "binName": "0 to +6 minutes",
        "count": 51,
        "percentOfTotal": 0.25
      },
      {
        "binMin": 360,
        "binMax": 600,
        "binName": "+6 to +10 minutes",
        "count": 32,
        "percentOfTotal": 0.1568627450980392
      },
      {
        "binMin": 600,
        "binMax": 1200,
        "binName": "+10 to +20 minutes",
        "count": 90,
        "percentOfTotal": 0.4411764705882353
      }
    ]
  },
  "layer": [
    {"mark": "bar"},
    {
      "transform": [
        {
          "calculate": "format(datum.percentOfTotal, '.0%')",
          "as": "perc_total"
        },
        {
          "calculate": "datum.count+' (' +datum.perc_total +')'",
          "as": "countPercentText"
        }
      ],
      "mark": {
        "type": "text",
        "align": "center",
        "yOffset": -10,
        "fontSize": 18
      },
      "encoding": {"text": {"field": "countPercentText", "type": "ordinal"}}
    }
  ],
  "encoding": {
    "x": {
      "field": "binName",
      "type": "nominal",
      "title": "Wait Time for Transfer (Minutes)",
      "axis": {"titleFontSize": 18, "labelAngle": 0, "labelFontSize": 14},
      "sort": {"field": "binMin"}
    },
    "y": {
      "field": "count",
      "type": "quantitative",
      "title": "Total Transfers",
      "axis": {"titleFontSize": 18, "labelFontSize": 14}
    },
    "color": {
      "legend": false,
      "field": "binMin",
      "scale": {"range": ["red", "orange", "green", "yellowgreen"]}
    }
  }
}

Upvotes: 1

Related Questions