Search code examples
powerbivisualizationpowerbi-desktopvega-litedeneb

vega lite colour text using a field


I have a stacked bar chart with text marks that I want coloured according to field 'text_value'.

This is what I have now, however the top text values should be coloured black according to the color condition in the text mark encoding.

not working example

{
"data": {
    "values": [
      {"category": "a", "xval": 1, "yval": "top", "text_val": 1},
      {"category": "b", "xval": 5, "yval": "top", "text_val": 1},
      {"category": "c", "xval": 8, "yval": "top", "text_val": 1},
      {"category": "a", "xval": 3, "yval": "bottom", "text_val": 2},
      {"category": "b", "xval": 1, "yval": "bottom", "text_val": 2},
      {"category": "c", "xval": 9, "yval": "bottom", "text_val": 2}
    ]
  },
  "encoding": {
    "y": {
      "title": null,
      "field": "yval",
      "sort": "descending"
    }
  },
  "layer": [
    {
      "mark": {
        "type": "bar",
        "tooltip": true
      },
      "encoding": {
        "x": {
          "title": null,
          "field": "xval",
          "type": "quantitative",
          "aggregate": "sum"
        },
        "color": {"field": "category"},
        "order": {"field": "category"}
      }
    },
    {
      "mark": {
        "type": "text",
        "tooltip": true,
        "fontSize": 100
      },
      "encoding": {
        "x": {
          "title": null,
          "field": "xval",
          "type": "quantitative",
          "aggregate": "sum",
          "stack": "zero",
          "bandPosition": 0.5
        },
        "text": {
          "title": null,
          "field": "xval",
          "type": "quantitative",
          "aggregate": "sum"
        },
        "color": {
          "condition": {
            "test": "datum.text_val == 1",
            "value": "black"
          },
          "value": "white"
        },
        "order": {"field": "category"}
      }
    }
  ]
}

Please note: It seems the 'text_value' field needs to be used somewhere else, but I don't need it anywhere except the condition. Also the aggregation must be sum, as this is a simplified example.


Solution

  • UPDATE START

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "height": 200,
      "width": 800,
      "data": {
        "values": [
          {"category": "a", "xval": 1, "yval": "top", "text_val": 1},
          {"category": "b", "xval": 5, "yval": "top", "text_val": 1},
          {"category": "c", "xval": 8, "yval": "top", "text_val": 1},
          {"category": "a", "xval": 3, "yval": "bottom", "text_val": 2},
          {"category": "b", "xval": 1, "yval": "bottom", "text_val": 2},
          {"category": "c", "xval": 9, "yval": "bottom", "text_val": 2}
        ]
      },
      "transform": [{"stack": "xval", "as": ["v1", "v2"], "groupby": ["yval"]},
       {"calculate": "((datum.v2 - datum.v1)/2) + datum.v1", "as": "mid"},],
      "encoding": {
        "y": {"title": null, "field": "yval", "sort": "descending"},
        "x2": {"field": "v2", "type": "quantitative"}
      },
      "layer": [
        {
          "mark": {"type": "bar", "tooltip": true},
          "encoding": {
            "x": {"title": null, "field": "v1", "type": "quantitative"},
            "color": {"field": "category"}
          }
        },
        {
          "mark": {"type": "text", "tooltip": true, "fontSize": 100},
          "encoding": {
              "x": {"title": null, "field": "mid", "type": "quantitative"},
            "text": {"title": null, "field": "xval", "type": "quantitative"},
            "color": {
              "condition": {"test": "datum.text_val == 1", "value": "black"},
              "value": "white"
            }
          }
        }
      ]
    }
    

    UPDATE END

    Your hidden aggregate transform here:

    enter image description here

    is resulting in this:

    enter image description here

    i.e. the column you are referring to is lost.

    You can either create a proper transform to do your own aggregate or instead just use a value that is available like yval

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "height": 200,
      "data": {
        "values": [
          {"category": "a", "xval": 1, "yval": "top", "text_val": 1},
          {"category": "b", "xval": 5, "yval": "top", "text_val": 1},
          {"category": "c", "xval": 8, "yval": "top", "text_val": 1},
          {"category": "a", "xval": 3, "yval": "bottom", "text_val": 2},
          {"category": "b", "xval": 1, "yval": "bottom", "text_val": 2},
          {"category": "c", "xval": 9, "yval": "bottom", "text_val": 2}
        ]
      },
      "encoding": {"y": {"title": null, "field": "yval", "sort": "descending"}},
      "layer": [
        {
          "mark": {"type": "bar", "tooltip": true},
          "encoding": {
            "x": {
              "title": null,
              "field": "xval",
              "type": "quantitative",
              "aggregate": "sum"
            },
            "color": {"field": "category"},
            "order": {"field": "category"}
          }
        },
        {
          "mark": {"type": "text", "tooltip": true, "fontSize": 100},
          "encoding": {
            "x": {
              "title": null,
              "field": "xval",
              "type": "quantitative",
              "aggregate": "sum",
              "stack": "zero",
              "bandPosition": 0.5
            },
            "text": {
              "title": null,
              "field": "xval",
              "type": "quantitative",
              "aggregate": "sum"
            },
            "color": {
              "condition": {"test": "datum.yval == 'top'", "value": "black"},
              "value": "white"
            },
            "order": {"field": "category"}
          }
        }
      ]
    }