Search code examples
vega-lite

Plot two "columns" of data having two different orders of magnitude using vega-lite


(This is a follow up on this question)

Assume my data looks like:

[
    {"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
    {"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
    {"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
    {"date": "2019-01-04", "foo": 20000,  "bar": 60, "goo": 20}
]

And my plot is:

{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"description": "Stock prices of 5 Tech Companies over Time.",
"width": 1200,
"height": 450,
"data": { "url": "data.json" },
"mark": {
    "type": "line",
    "point": true
},
"transform": [
    { "fold": ["foo", "bar", "goo"] }
],
"encoding": {
    "x": { "field": "date", "type": "temporal" },
    "y": { "field": "value", "type": "quantitative" },
    "color": { "field": "key", "type": "nominal" },
    "scale": {"zero": false}
},
"resolve": { "scale": { "y": "independent" } }
}

As you can see, due to the different order of magnitude of foo and the other two columns, the plot is not helpful. How can I have a secondary y-axis and (mention it in the legend)?


Solution

  • You can do that by combining layering with the fold transform. Here is how you might modify your example (vega editor link):

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v3.json",
      "width": 1200,
      "height": 450,
      "data": {
        "values": [
          {"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
          {"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
          {"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
          {"date": "2019-01-04", "foo": 20000, "bar": 60, "goo": 20}
        ]
      },
      "transform": [{"fold": ["foo", "bar", "goo"]}],
      "encoding": {
        "x": {"field": "date", "type": "temporal"},
        "y": {"field": "value", "type": "quantitative"},
        "color": {"field": "key", "type": "nominal"}
      },
      "layer": [
        {
          "mark": {"type": "line", "point": true},
          "transform": [{"filter": "datum.key == 'foo'"}]
        },
        {
          "mark": {"type": "line", "point": true},
          "transform": [{"filter": "datum.key != 'foo'"}]
        }
      ],
      "resolve": {"scale": {"y": "independent"}}
    }
    

    enter image description here

    You could then go on to modify the axis titles by specifying the y encoding & title within each layer. Here is an example (vega editor link):

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v3.json",
      "width": 1200,
      "height": 450,
      "data": {
        "values": [
          {"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
          {"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
          {"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
          {"date": "2019-01-04", "foo": 20000, "bar": 60, "goo": 20}
        ]
      },
      "transform": [{"fold": ["foo", "bar", "goo"]}],
      "encoding": {
        "x": {"field": "date", "type": "temporal"},
        "color": {"field": "key", "type": "nominal"}
      },
      "layer": [
        {
          "mark": {"type": "line", "point": true},
          "encoding": {
            "y": {"field": "value", "type": "quantitative", "title": "Foo Value"}
          },
          "transform": [{"filter": "datum.key == 'foo'"}]
        },
        {
          "mark": {"type": "line", "point": true},
          "encoding": {
            "y": {
              "field": "value",
              "type": "quantitative",
              "title": "Bar/Goo Value"
            }
          },
          "transform": [{"filter": "datum.key != 'foo'"}]
        }
      ],
      "resolve": {"scale": {"y": "independent"}}
    }
    

    enter image description here