Search code examples
vega-litedeneb

Conditional opacity for stacked bar chart text


I want to hide text labels when the stack bar width is under 10% of the total bar width, indicated by the 'x' in this mock up.

mock up chart

I can hide these based on their absolute value, however I don't want to do that because when the chart is filtered, then their relative value becomes large enough to want to show the labels.

There are many records with the same category and y-value, so they have to be aggregated.

Here's my attempt, I'm able to hide the labels as required if I show the percentage, percentage version - which I don't want

however I want to show the actual values (when I try that, it just shows all the labels):

{
  "data": {"name": "dataset"},
  "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"}
      }
    },
    {
      "transform": [
        {
          "joinaggregate": [
            {
              "op": "sum",
              "field": "xval",
              "as": "xtotal"
            }
          ],
          "groupby": ["yval"]
        },
        {
          "joinaggregate": [
            {
              "op": "sum",
              "field": "xval",
              "as": "cat_total"
            }
          ],
          "groupby": [
            "yval",
            "category"
          ]
        },
        {
          "calculate": "datum.cat_total/datum.xtotal",
          "as": "cat_perc"
        }
      ],
      "mark": {"type": "text"},
      "encoding": {
        "x": {
          "field": "xval",
          "type": "quantitative",
          "aggregate": "sum",
          "stack": "zero",
          "bandPosition": 0.5
        },
        "text": {"field": "cat_perc", "format": ".0%"},
        "color": {"value": "black"},
        "opacity": {
          "condition": {
            "test": "datum.cat_perc < 0.1",
            "value": 0
          },
          "value": 1
          
        },
        "order": {"field": "category"}
      }
    }
  ]
}

I want to replace this

"text": {"field": "cat_perc", "format": ".0%"},

with this

"text": {"field": "cat_total"},

Dataset:

category,xval,yval
a,1,top
a,3,bottom
b,1,bottom
b,5,top
c,8,top
c,9,bottom

Solution

  • Since cat_perc is not used then it is not available for other logic since it is not included in the dataset. When I add this value in a tool-tip then it works fine. Hope this helps.

    {
    "data": {
        "values": [
          {"category": "a", "xval": 1, "yval": "top"},
          {"category": "b", "xval": 5, "yval": "top"},
          {"category": "c", "xval": 8, "yval": "top"},
          {"category": "a", "xval": 3, "yval": "bottom"},
          {"category": "b", "xval": 1, "yval": "bottom"},
          {"category": "c", "xval": 9, "yval": "bottom"}
        ]
      },
      "encoding": {
        "y": {
          "title": null,
          "field": "yval",
          "sort": "descending"
        },
        "tooltip": [
              {"field": "category", "type": "nominal", "title": "Category"},
              {"field": "yval", "type": "nominal", "title": "Y"},
              {
                "field": "xval",
                "type": "quantitative",
                "title": "X",
                "format": ".0f"
              },
              {
                "field": "cat_perc",
                "type": "quantitative",
                "title": "%",
                "format": ".1f"
              }
            ]
      },
      "layer": [
        {
          "mark": {
            "type": "bar",
            "tooltip": true
          },
          "encoding": {
            "x": {
              "title": null,
              "field": "xval",
              "type": "quantitative",
              "aggregate": "sum"
            },
            "color": {"field": "category"},
            "order": {"field": "category"}
          }
        },
        {
          "transform": [
            {
              "joinaggregate": [
                {
                  "op": "sum",
                  "field": "xval",
                  "as": "xtotal"
                }
              ],
              "groupby": ["yval"]
            },
            {
              "joinaggregate": [
                {
                  "op": "sum",
                  "field": "xval",
                  "as": "cat_total"
                }
              ],
              "groupby": [
                "yval",
                "category"
              ]
            },
            {
              "calculate": "datum.cat_total/datum.xtotal",
              "as": "cat_perc"
            }
          ],
          "mark": {"type": "text"},
          "encoding": {
            "x": {
              "field": "xval",
              "type": "quantitative",
              "aggregate": "sum",
              "stack": "zero",
              "bandPosition": 0.5
            },
            "text": {"field": "xval", "format": ".0f"},
            "color": {"value": "black"},
            "opacity": {
              "condition": {
                "test": "datum.cat_perc < 0.1",
                "value": 0
              },
              "value": 1
              
            },
            "order": {"field": "category"}
          }
        }
      ]
    }