Search code examples
data-visualizationvega-lite

How to add vertical rules as new layer and same x-axis?


enter image description here

When add the strips as a new layer (in the 2-layers chart), stops to work: there are no visualization and a "WARN Cannot project a selection on encoding channel "y", which has no field".

The first two layer-definitions bellow was working fine when only two lines.

vglSpec.push(['#vis2a',{
    $schema: vglVers,
    data: {"url":"MyDataset1"},
    // old "encoding": { x: {"field": "instant", "type": "temporal"} }
    width:680,
    layer: [
        {
            "mark": {"stroke": "#68C", "type": "line", "point": true},
            "encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
                "field": "n_count", 
                "type": "quantitative"
            }},
            "selection": {"grid": {"type":"interval", "bind":"scales"}}   //zoom
        },
        {
            "mark": {"stroke": "red", "type": "line", "strokeOpacity": 0.4},
            "encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
                "field": "instant_totmin", 
                "type": "quantitative"
            }}
        },
        {
            "mark": "rule",
            "data": {"url":"MyDataset2"}, // little subset of instant of Dataset1
            "encoding": {
              "x": { "field": "instant", "type": "temporal"},
              "color": {"value": "yellow"},
              "size": {"value": 5}
            },
            //resolve:? x is same axis and the only visualization field
        }
    ],
    resolve: {"scale": {"y": "independent"}}
}]);

PS: only removed names and titles, all real script.


Emulating with dummy data: working fine!

Please click on the 3rd example of rule guide... And replace or adapt it for this VEGA-lite script:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
  "data": {"url": "data/movies.json"},
  "layer": [
    { 
      "mark": "bar",
      "encoding": {
        "x": {"bin": true, "field": "IMDB_Rating", "type": "quantitative"},
        "y": {"aggregate": "count", "type": "quantitative"}
      }
    },
    {
      "mark": "rule",
      "data": {"values": [{"IMDB_Rating":3.5},{"IMDB_Rating":7.8}]},
      "encoding": {
        "x": { "field": "IMDB_Rating","type": "quantitative" },
        "color": {"value": "yellow"},
        "size": {"value": 4}
      }
    }
  ]
}

Solution

  • You're using an independent y-scale, and the y-scale of a rule mark with no y encoding is not well defined. The best way to address this is probably to combine the rule mark with one of the other layers, so it can use that y scale:

    vglSpec.push(['#vis2a',{
        $schema: vglVers,
        data: {"url":"MyDataset1"},
        // old "encoding": { x: {"field": "instant", "type": "temporal"} }
        width:680,
        layer: [
            {
                "mark": {"stroke": "#68C", "type": "line", "point": true},
                "encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
                    "field": "n_count", 
                    "type": "quantitative"
                }},
                "selection": {"grid": {"type":"interval", "bind":"scales"}}   //zoom
            },
            {
              layer: [
                {
                    "mark": {"stroke": "red", "type": "line", "strokeOpacity": 0.4},
                    "encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
                        "field": "instant_totmin", 
                        "type": "quantitative"
                    }}
                },
                {
                    "mark": "rule",
                    "data": {"url":"MyDataset2"}, // little subset of instant of Dataset1
                    "encoding": {
                      "x": { "field": "instant", "type": "temporal"},
                      "color": {"value": "yellow"},
                      "size": {"value": 5}
                    },
                //resolve:? x is same axis and the only visualization field
                }
              ]
            }
        ],
        resolve: {"scale": {"y": "independent"}}
    }]);
    

    (note, I've not actually tried this solution because you didn't include data in your question, but the approach should work).