2

Is it possible to create parallel coordinates in Vega-Lite? I'm looking for a simple yet powerful plotting library for JavaScript and support for parallel coordinates is a requirement.

I have googled it but only found how to do it in Vega.

HelloGoodbye
  • 3,624
  • 8
  • 42
  • 57
  • I've used this library before, not sure if it'll help or not: https://syntagmatic.github.io/parallel-coordinates/ – JoshG Feb 13 '19 at 13:40
  • @AndroidNoobie Interesting, but seems to be very restricted in functionality (it can only draw parallel coordinates) – HelloGoodbye Feb 13 '19 at 14:31
  • But the underlying library (d3.js) can draw a wide range of plot types. – JoshG Feb 13 '19 at 14:36
  • @AndroidNoobie d3.js is an alternative—I know it's very powerful, but I wouldn't consider it especially simple since you have to write quite a lot of code to draw a plot compared to many other visualization libraries – HelloGoodbye Feb 13 '19 at 15:14

2 Answers2

4

Yes, you can create a parallel coordinates plot in Vega-Lite by combining a window transform and a fold transform. Here is an example with the Iris dataset (vega editor link):

{
  "data": {
    "url": "data/iris.json"
  },
  "transform": [
    {"window": [{"op": "count", "as": "index"}]},
    {"fold": ["petalLength", "petalWidth", "sepalLength", "sepalWidth"]}
  ],
  "mark": "line",
  "encoding": {
    "color": {"type": "nominal", "field": "species"},
    "detail": {"type": "nominal", "field": "index"},
    "opacity": {"value": 0.3},
    "x": {"type": "nominal", "field": "key"},
    "y": {"type": "quantitative", "field": "value"}
  },
  "width": 600,
  "height": 300
}

enter image description here

Notice we use a window transform to construct an index, followed by a fold transform to restructure the data for plotting.

jakevdp
  • 77,104
  • 11
  • 125
  • 160
  • Nice! Would it also be possible to add a vertical axis to each of the coordinates to that graph, like in the Vega example? – HelloGoodbye Feb 13 '19 at 23:15
  • No, vega-lite only supports multiple scales in the case of faceted or concatenated plots, in which case you can't draw lines between the axes. – jakevdp Feb 13 '19 at 23:16
  • Okay, thanks. I think it could be useful to feature this example on the [Vega-Lite page](https://vega.github.io/vega-lite/examples/) so that there was an example that showed how to draw parallel coordinates on there, too :) – HelloGoodbye Feb 13 '19 at 23:21
  • On the other hand, Vega-Lite is doesn't seem to handle parallel coordinate plots very well if they can't use multiple scales, since different coordinates may have very different distributions and hence require different affine transformations, which is not possible (or at least can't be represented) with only one scale. So perhaps a parallel coordinates example wouldn't be right. – HelloGoodbye Feb 14 '19 at 08:19
  • Conclusion: I'll stick with Vega for now :) – HelloGoodbye Feb 14 '19 at 08:20
  • Would that be possible to change the order of the keys on xAxis? Right now, they are following alphabet order – Oscar Zhang Feb 18 '23 at 05:50
4

Building on @jakevdp's answer, here is an improved version that normalizes each variables and manually draw axes with rule, text and tick marks.

Note that parallel coordinates are often useful when you have interactivity though, so there is more work to be done here.

{
  "data": {
    "url": "data/iris.json"
  },
  "width": 600,
  "height": 300,
  "transform": [
    {"window": [{"op": "count", "as": "index"}]},
    {"fold": ["petalLength", "petalWidth", "sepalLength", "sepalWidth"]},
    {
      "window": [
        {"op": "min", "field": "value", "as": "min"},
        {"op": "max", "field": "value", "as": "max"}
      ],
      "frame": [null, null],
      "groupby": ["key"]
    },
    {
      "calculate": "(datum.value - datum.min) / (datum.max-datum.min)",
      "as": "norm_val"
    },
    {
      "calculate": "(datum.min + datum.max) / 2",
      "as": "mid"
    }
  ],
  "layer": [{
    "mark": {"type": "rule", "color": "#ccc", "tooltip": null},
    "encoding": {
      "detail": {"aggregate": "count", "type": "quantitative"},
      "x": {"type": "nominal", "field": "key"}
    }
  }, {
    "mark": "line",
    "encoding": {
      "color": {"type": "nominal", "field": "species"},
      "detail": {"type": "nominal", "field": "index"},
      "opacity": {"value": 0.3},
      "x": {"type": "nominal", "field": "key"},
      "y": {"type": "quantitative", "field": "norm_val", "axis": null},
      "tooltip": [{
        "field": "petalLength"
      }, {
        "field": "petalWidth"
      }, {
        "field": "sepalLength"
      }, {
        "field": "sepalWidth"
      }]
    }
  },{
    "encoding": {
      "x": {"type": "nominal", "field": "key"}, 
      "y": {"value": 0}
    },
    "layer": [{
      "mark": {"type": "text", "style": "label"},
      "encoding": {
        "text": {"aggregate": "max", "field": "max", "type": "quantitative"}
      }
    }, {
      "mark": {"type": "tick", "style": "tick", "size": 8, "color": "#ccc"}
    }]
  },{

    "encoding": {
      "x": {"type": "nominal", "field": "key"}, 
      "y": {"value": 150}
    },
    "layer": [{
      "mark": {"type": "text", "style": "label"},
      "encoding": {
        "text": {"aggregate": "min", "field": "mid", "type": "quantitative"}
      }
    }, {
      "mark": {"type": "tick", "style": "tick", "size": 8, "color": "#ccc"}
    }]
  },{
    "encoding": {
      "x": {"type": "nominal", "field": "key"}, 
      "y": {"value": 300}
    },
    "layer": [{
      "mark": {"type": "text", "style": "label"},
      "encoding": {
        "text": {"aggregate": "min", "field": "min", "type": "quantitative"}
      }
    }, {
      "mark": {"type": "tick", "style": "tick", "size": 8, "color": "#ccc"}
    }]
  }],
  "config": {
    "axisX": {"domain": false, "labelAngle": 0, "tickColor": "#ccc", "title": false},
    "view": {"stroke": null},
    "style": {
      "label": {"baseline": "middle", "align": "right", "dx": -5, "tooltip": null},
      "tick": {"orient": "horizontal", "tooltip": null}
    }
  }
}

enter image description here

kanitw
  • 874
  • 10
  • 19