Parallel Coordinates Plot in JavaScript

How to make D3.js-based parallel coordinates plots in Plotly.js.


New to Plotly?

Plotly is a free and open-source graphing library for JavaScript. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

Parallel coordinates are richly interactive by default. Drag the lines along the axes to filter regions and drag the axis names across the plot to rearrange variables: IPython terminal

var trace = {
  type: 'parcoords',
  line: {
    color: 'blue'
  },
  
  dimensions: [{
    range: [1, 5],
    constraintrange: [1, 2],
    label: 'A',
    values: [1,4]
  }, {    
    range: [1,5],
    label: 'B',
    values: [3,1.5],
    tickvals: [1.5,3,4.5]
  }, {
    range: [1, 5],
    label: 'C',
    values: [2,4],
    tickvals: [1,2,4,5],
    ticktext: ['text 1','text 2','text 4','text 5']
  }, {
    range: [1, 5],
    label: 'D',
    values: [4,2]
  }]
};

var data = [trace]

Plotly.newPlot('myDiv', data);
Click to copy
d3.csv('https://raw.githubusercontent.com/bcdunbar/datasets/master/iris.csv', function(err, rows){

function unpack(rows, key) {
  return rows.map(function(row) {
    return row[key];
  });
}

var data = [{
  type: 'parcoords',
  pad: [80,80,80,80],
  line: {
    color: unpack(rows, 'species_id'),
    colorscale: [[0, 'red'], [0.5, 'green'], [1, 'blue']]
  },

  dimensions: [{
    range: [2, 4.5],
    label: 'sepal_width',
    values: unpack(rows, 'sepal_width')
  }, {
    constraintrange: [5, 6],
    range: [4,8],
    label: 'sepal_length',
    values: unpack(rows, 'sepal_length')
  }, {
    label: 'petal_width',
    range: [0, 2.5],
    values: unpack(rows, 'petal_width')
  }, {
    label: 'petal_length',
    range: [1, 7],
    values: unpack(rows, 'petal_length')
  }]
}];

var layout = {
  width: 800
};

Plotly.newPlot('myDiv', data, layout);

});
Click to copy
22.533.544.5sepal_width4.5245678sepal_length8400.511.522.5petal_width2.501234567petal_length71
d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/iris-id.csv', function(err, rows){

function unpack(rows, key) {
  return rows.map(function(row) {
    return row[key];
  });
}

var data = [{
  type: 'parcoords',
  pad: [80,80,80,80],
  line: {
    color: unpack(rows, 'species_id'),
    colorscale: [[0, 'red'], [0.5, 'green'], [1, 'blue']]
  },

  dimensions: [{
    range: [2, 4.5],
    label: 'sepal_width',
    values: unpack(rows, 'sepal_width')
  }, {
    constraintrange: [5, 6],
    range: [4,8],
    label: 'sepal_length',
    values: unpack(rows, 'sepal_length')
  }, {
    label: 'petal_width',
    range: [0, 2.5],
    values: unpack(rows, 'petal_width')
  }, {
    label: 'petal_length',
    range: [1, 7],
    values: unpack(rows, 'petal_length')
  }]
}];

var layout = {
  width: 800,
  annotations: [
	  {showarrow: false,
      text: 'Higher sepal width',
      x: 0, y: 1, xref: 'paper', yref: 'paper'},
	  {showarrow: false,
      text: 'Lower petal width and length',
      x: 0.9, y: .25, xref: 'paper', yref: 'paper'
    }]
};

Plotly.newPlot('myDiv', data, layout);

});
Click to copy
Higher sepal widthLower petal width and length22.533.544.5sepal_width4.5245678sepal_length8400.511.522.5petal_width2.501234567petal_length71
d3.csv('https://raw.githubusercontent.com/bcdunbar/datasets/master/parcoords_data.csv', function(err, rows){

function unpack(rows, key) {
  return rows.map(function(row) {
    return row[key];
  });
}

var data = [{
  type: 'parcoords',
  line: {
    showscale: true,
    reversescale: true,
    colorscale: 'Jet',
    cmin: -4000,
    cmax: -100,
    color: unpack(rows, 'colorVal')
  },

  dimensions: [{
    constraintrange: [100000, 150000],
    range: [32000, 227900],
    label: 'Block height',
    values: unpack(rows, 'blockHeight')
  }, {
    range: [0, 700000],
    label: 'Block width',
    values: unpack(rows, 'blockWidth')
  }, {
    label: 'Cylinder material',
    tickvals: [0, 0.5, 1, 2, 3],
    ticktext: ['A', 'AB', 'B', 'Y', 'Z'],
    values: unpack(rows, 'cycMaterial')
  }, {
    label: 'Block material',
    tickvals: [0, 1, 2, 3],
    range: [-1, 4],
    values: unpack(rows, 'blockMaterial')
  }, {
    range: [134, 3154],
    label: 'Total weight',
    visible: true,
    values: unpack(rows, 'totalWeight')
  }, {
    range: [9, 19984],
    label: 'Assembly penalty weight',
    values: unpack(rows, 'assemblyPW')
  }, {
    range: [49000, 568000],
    label: 'Height st width',
    values: unpack(rows, 'HstW')
  }, {
    range: [-28000, 196430],
    label: 'Min height width',
    values: unpack(rows, 'minHW')
  }, {
     range: [98453, 501789],
     label: 'Min width diameter',
     values: unpack(rows, 'minWD')
  }, {
    range: [1417, 107154],
    label: 'RF block',
    values: unpack(rows, 'rfBlock')
  }]
}];

Plotly.newPlot('myDiv', data);

});
Click to copy
−4000−3000−2000−100050k100k150k200kBlock height227.9k32k0100k200k300k400k500k600k700kBlock width700k0AABBYZCylinder material0123Block material50010001500200025003000Total weight31541345k10k15kAssembly penalty weight19.984k0.009k100k200k300k400k500kHeight st width568k49k050k100k150kMin height width196.43k−28k100k200k300k400k500kMin width diameter501.79k98.45k20k40k60k80k100kRF block107.15k1.42k