Search code examples
vega-litevega

How do you fix the rendered text in a hconcat pyramid chart?


Concat pyramid chart

I am trying to create a concat pyramid chart, but the text in the middle seems to have a problem rendering properly. Changing the field for mark text to something that is a number does not have this render problem. This is the example I followed to and modify from. Population Pyramid

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "spacing": 0,
  "hconcat": [
    {
      "transform": [
        { "filter": { "field": "sentiment", "equal": "negative" } }
      ],
      "encoding": {
        "y": { "field": "type", "title": null, "axis": null },
        "x": {
          "field": "sentiment",
          "aggregate": "count",
          "axis": null,
          "sort": "descending"
        }
      },
      "layer": [
        { "mark": "bar", "encoding": { "color": { "field": "channel" } } }
      ]
    },
    {
      "width": 100,
      "view": { "stroke": null },
      "mark": { "type": "text", "align": "center" },
      "encoding": {
        "y": { "field": "type", "axis": null },
        "text": { "field": "type" }
      }
    },
    {
      "mark": "bar",
      "transform": [
        { "filter": { "field": "sentiment", "equal": "positive" } }
      ],
      "encoding": {
        "color": { "field": "channel" },
        "y": { "field": "type", "axis": null },
        "x": { "field": "sentiment", "aggregate": "count", "axis": null }
      }
    }
  ],
  "config": { "view": { "stroke": null }, "axis": { "grid": false } },
  "data": {
    "values": [
      {
        "id": 1,
        "type": "shops",
        "channel": "line man",
        "sentiment": "negative"
      }
    ]
  }
}

Solution

  • Since you have not done any aggregation in your text chart, each text mark is drawn multiple times – once per corresponding row in the data. This stacking of multiple text marks is what makes it appear as if it's rendered poorly.

    To ensure that each text mark is only drawn once, you'll need to aggregate the data. There are a few ways to do this, but the easiest here is to use the argmin or argmax of an associated numerical column:

    "encoding": {
      "y": {"field": "type", "axis": null},
      "text": {"field": "type", "aggregate": {"argmin": "id"}}
    }