meta data for this page
Parallel Coordinates Plot Example
Here is an example of what a Parallel Coordinates Plot looks like with building simulation data. You can try filtering data by selecting a region on a coordinate. This plot type is excellent for visually analyzing sensitive design parameters to given performance indicators.
Sample chart
(If the chart below does not show, please reload this page.)
<html>
<head> <title>Parallel Coordinates</title> <script type="text/javascript" src="/vis/pcp/protovis.js"></script> <script type="text/javascript" src="/vis/pcp/data.js"></script> <style type="text/css">
#fig {
width: 880px; height: 560px;
}
#title {
position: absolute; top: 70px; left: 200px; padding: 10px; background: white;
}
large {
font-size: medium;
}
</style> </head> <body><div id="center"><div id="fig"> <script type="text/javascript+protovis">
var dims = pv.keys(units);
/* Sizing and scales. */ var w = 820,
h = 520, fudge = 0.5, x = pv.Scale.ordinal(dims).splitFlush(0, w), y = pv.dict(dims, function(t) pv.Scale.linear( cars.filter(function(d) !isNaN(d[t])), function(d) Math.floor(d[t])-fudge, function(d) Math.ceil(d[t]) +fudge ).range(0, h)), c = pv.dict(dims, function(t) pv.Scale.linear( cars.filter(function(d) !isNaN(d[t])), function(d) Math.floor(d[t])-fudge, function(d) Math.ceil(d[t]) +fudge ).range("steelblue", "brown"));
/* Interaction state. */ var filter = pv.dict(dims, function(t) {
return {min: y[t].domain()[0], max: y[t].domain()[1]}; }), active = "model";
/* The root panel. */ var vis = new pv.Panel()
.width(w) .height(h) .left(30) .right(30) .top(30) .bottom(20);
The parallel coordinates display. vis.add(pv.Panel) .data(cars) .visible(function(d) dims.every(function(t) (d[t] >= filter[t].min) && (d[t] ⇐ filter[t].max))) .add(pv.Line) .data(dims) .left(function(t, d) x(t)) .bottom(function(t, d) y[t](d[t])) .strokeStyle(“#ddd”) .lineWidth(1) .antialias(false); Rule per dimension. rule = vis.add(pv.Rule)
.data(dims) .left(x);
Dimension label rule.anchor(“top”).add(pv.Label) .top(-12) .font(“bold 10px sans-serif”) .text(function(d) units[d].name); The parallel coordinates display. var change = vis.add(pv.Panel);
var line = change.add(pv.Panel)
.data(cars) .visible(function(d) dims.every(function(t) (d[t] >= filter[t].min) && (d[t] <= filter[t].max))) .add(pv.Line) .data(dims) .left(function(t, d) x(t)) .bottom(function(t, d) y[t](d[t])) .strokeStyle(function(t, d) c[active](d[active])) .lineWidth(1);
Updater for slider and resizer. function update(d) { var t = d.dim; filter[t].min = Math.max(y[t].domain()[0], y[t].invert(h - d.y - d.dy)); filter[t].max = Math.min(y[t].domain()[1], y[t].invert(h - d.y)); active = t; change.render(); return false; } Updater for slider and resizer. function selectAll(d) {
if (d.dy < 3) { var t = d.dim; filter[t].min = Math.max(y[t].domain()[0], y[t].invert(0)); filter[t].max = Math.min(y[t].domain()[1], y[t].invert(h)); d.y = 0; d.dy = h; active = t; change.render(); } return false;
}
/* Handle select and drag */ var handle = change.add(pv.Panel)
.data(dims.map(function(dim) { return {y:0, dy:h, dim:dim}; })) .left(function(t) x(t.dim) - 30) .width(60) .fillStyle("rgba(0,0,0,.001)") .cursor("crosshair") .event("mousedown", pv.Behavior.select()) .event("select", update) .event("selectend", selectAll) .add(pv.Bar) .left(25) .top(function(d) d.y) .width(10) .height(function(d) d.dy) .fillStyle(function(t) t.dim == active ? c[t.dim]((filter[t.dim].max + filter[t.dim].min) / 2) : "hsla(0,0,50%,.5)") .strokeStyle("white") .cursor("move") .event("mousedown", pv.Behavior.drag()) .event("dragstart", update) .event("drag", update);
handle.anchor(“bottom”).add(pv.Label)
.textBaseline("top") .text(function(d) filter[d.dim].min.toFixed(0) + units[d.dim].unit);
handle.anchor(“top”).add(pv.Label)
.textBaseline("bottom") .text(function(d) filter[d.dim].max.toFixed(0) + units[d.dim].unit);
vis.render();
</script> </div></div></body>
</html>
Discussion