VEGA Lite, How to create separate Legends for concatenated charts

I am trying to create a visualization of multiple stacked bar graphs and I want to have each chart use its own legend, the problem is that the legend generated by Vegalite for each graph contains all fields, even the ones not present on that particular graph.

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A dashboard with cross-highlighting.",
  "data": {"url": "data/movies.json"},
  "vconcat": [

    {
      "width": 400,
      "height": 150,
      "mark": "bar",
      "params": [{
        "name": "main",
        "select": {"type": "point", "encodings": ["x"]}
      }],
      "encoding": {
        "x": {"field": "Major Genre", "axis": {"labelAngle": -40}},
        "y": {"aggregate": "count"},
        "color": {
          "condition": {
            "param": "main",
            "field": "MPAA Rating"
          },
          "value": "lightgrey"
        }
      }
    },

    {
      "width": 400,
      "height": 150,  
      "transform": [{
        "filter": {"param": "main"}
      }],
      "mark": "bar",
      "params": [{
        "name": "i",
        "select": {"type": "point", "encodings": ["x"]}
      }],
      "encoding": {
        "x": {
          "field": "MPAA Rating"
        },
        "y": {"aggregate": "count"},
        "color": {
          "condition": {
            "param": "i",
            "field": "Source"
          },
          "value": "lightgrey"
          
        }
        
      }
    },

    {
      "width": 400,
      "height": 150,  
      "transform": [
        {"filter": {"param": "main"}},
        {"filter": {"param": "i"}}
        ],
      "mark": "bar",
      "encoding": {
        "x": {
          "field": "Source"
        },
        "y": {"aggregate": "count"},
        "color": {
          "field": "Source",
          "legend": {
            "values": {"expr":""}
          }
        }
      }
    }
  ],
  "resolve": {
    "legend": {
      "opacity": "independent",
      "color": "independent",
      "size": "independent"
      
    }
  }
}

The resulting graph can be seen here:
You can use the online editor.

The desired behavior for this example would be to have the first graph’s legend only display MPAA ratings and the seconds graph’s legend only display source material.
This is shown here: Image of desired legends

I have tried manually declaring which values to show in the legend using:

"legend": {
    "values": ['x', 'y', 'z']
}

But I really need a way to do it automatically

>Solution :

I think your resolve just needs cleaning up.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A dashboard with cross-highlighting.",
  "data": {"url": "data/movies.json"},

  "vconcat": [
    
    {
      "width": 400,
      "height": 150,
      "mark": "bar",
      "params": [
        {"name": "main", "select": {"type": "point", "encodings": ["x"]}}
      ],
      "encoding": {
        "x": {"field": "Major Genre", "axis": {"labelAngle": -40}},
        "y": {"aggregate": "count"},
        "color": {
          "condition": {"param": "main", "field": "MPAA Rating"},
          "value": "lightgrey"
        }
      }
    },
    {
      "width": 400,
      "height": 150,
      "transform": [{"filter": {"param": "main"}}],
      "mark": "bar",
      "params": [
        {"name": "i", "select": {"type": "point", "encodings": ["x"]}}
      ],
      "encoding": {
        "x": {"field": "MPAA Rating"},
        "y": {"aggregate": "count"},
        "color": {
          "condition": {"param": "i", "field": "Source"},
          "value": "lightgrey"
        }
      }
    },
    {
      "width": 400,
      "height": 150,
      "transform": [{"filter": {"param": "main"}}, {"filter": {"param": "i"}}],
      "mark": "bar",
      "encoding": {
        "x": {"field": "Source"},
        "y": {"aggregate": "count"},
        "color": {"field": "Source", "legend": false}
      }
    }
  ],
 "resolve": {"scale": {"color": "independent"}}
}

Leave a Reply