Search code examples
jsonchartsvisualizationvega

Unable to set text color based on condition in vega specification


I have tried all the suggestions made by ChatGPT and every variation I can think of to get the following spec to work so that the text values will change color at the top of the chart. If you use the vega data viewing tool you can see that there is a price/budget value defined for every date you can also display one or all of the values as text but the text is always colored whatever the default color is (blue in this case) even using 1=1 does not evaluate correctly.

Thoughts?

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "Monthly stock prices of a Tech Company.",
  "background": "white",
  "padding": 5,
  "width": 400,
  "height": 200,
  "data": [
    {
      "name": "source_0",
      "values": [
        {"date": "2021-01-01", "symbol": "AAPL", "price": 150, "budget": 110},
        {"date": "2021-02-01", "symbol": "AAPL", "price": 100, "budget": 50},
        {"date": "2022-03-01", "symbol": "AAPL", "price": 90, "budget": 90},
        {"date": "2022-04-01", "symbol": "AAPL", "price": 130, "budget": 150}
      ],
      "transform": [
        {
          "type": "filter",
          "expr": "datum.symbol === 'AAPL'"
        },
        {
          "type": "formula",
          "expr": "slice(datum.date, 0, 7)",
          "as": "year_month"
        }
        ,
        {
          "type": "formula",
            "expr": "(datum.price>=datum.budget) ? 1 : 0"
            ,"as":"isgreen"
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "band",
      "domain": {"data": "source_0", "field": "year_month"},
      "range": "width",
      "padding": 0.1
    },
    {
      "name": "y",
      "type": "linear",
      "domain": [0, 200],
      "range": [200, 0],
      "nice": true
    }
  ],
  "axes": [
    {
      "scale": "x",
      "orient": "bottom",
      "title": "Month"
    },
    {
      "scale": "y",
      "orient": "left",
      "title": "Price ($)"
    }
  ],
  "marks": [
    {
      "type": "text",
      "from": {"data": "source_0"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "year_month", "band": 0.5},
          "y": {"scale": "y", "field": "budget"},
         "text": {"field":"budget"},
          "align": {"value": "center"},
          "baseline": {"value": "middle"} 
           , "fill": {
          "condition": {
            "test": "1=1",
            "value": "green"
          },
          "value": "blue"
        }

        
      }
      }
    }
  ]
}

Solution

  • Easier to use a signal.

    enter image description here

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "description": "Monthly stock prices of a Tech Company.",
      "background": "white",
      "padding": 5,
      "width": 400,
      "height": 200,
      "data": [
        {
          "name": "source_0",
          "values": [
            {"date": "2021-01-01", "symbol": "AAPL", "price": 150, "budget": 110},
            {"date": "2021-02-01", "symbol": "AAPL", "price": 100, "budget": 50},
            {"date": "2022-03-01", "symbol": "AAPL", "price": 90, "budget": 90},
            {"date": "2022-04-01", "symbol": "AAPL", "price": 130, "budget": 150}
          ],
          "transform": [
            {"type": "filter", "expr": "datum.symbol === 'AAPL'"},
            {
              "type": "formula",
              "expr": "slice(datum.date, 0, 7)",
              "as": "year_month"
            },
            {
              "type": "formula",
              "expr": "(datum.price>=datum.budget) ? 1 : 0",
              "as": "isgreen"
            }
          ]
        }
      ],
      "scales": [
        {
          "name": "x",
          "type": "band",
          "domain": {"data": "source_0", "field": "year_month"},
          "range": "width",
          "padding": 0.1
        },
        {
          "name": "y",
          "type": "linear",
          "domain": [0, 200],
          "range": [200, 0],
          "nice": true
        }
      ],
      "axes": [
        {"scale": "x", "orient": "bottom", "title": "Month"},
        {"scale": "y", "orient": "left", "title": "Price ($)"}
      ],
      "marks": [
        {
          "type": "text",
          "from": {"data": "source_0"},
          "encode": {
            "enter": {
              "x": {"scale": "x", "field": "year_month", "band": 0.5},
              "y": {"scale": "y", "field": "budget"},
              "text": {"field": "budget"},
              "align": {"value": "center"},
              "baseline": {"value": "middle"},
              "fill": {
                "signal":  "datum.isgreen==1?'green':'blue'",
              
              }
            }
          }
        }
      ]
    }