Skip to content

Instantly share code, notes, and snippets.

@sebastian-meier
Last active December 3, 2020 21:22
Show Gist options
  • Select an option

  • Save sebastian-meier/03df214f456fc100526a to your computer and use it in GitHub Desktop.

Select an option

Save sebastian-meier/03df214f456fc100526a to your computer and use it in GitHub Desktop.
Interactive Parallel Coordinates with Ordinal Axis

An interactive parallel coordinate visualization with brushing and resorting of axis.

This gist is based on those three gists: The original paralle coordinate example was written by Mike Bostock, link Jason Davies added interactions, here And Kai added an example for ordinal axis, here

I simply combined the interactions and the ordinal axis.

column1 column2 column3 column4 column5 column6 column7
0.6921182430814952 value_4 0.16983658075332642 value_2 0.39996363199315965 value_2 value_3
0.902767694555223 value_4 0.41946926806122065 value_2 0.7558158154133707 value_2 value_2
0.2120242533273995 value_4 0.6112170105334371 value_2 0.9572873150464147 value_3 value_3
0.1104319638106972 value_2 0.8734128624200821 value_2 0.0746757066808641 value_2 value_3
0.6343169978354126 value_3 0.9712891113013029 value_2 0.6163364436943084 value_3 value_4
0.04087074683047831 value_4 0.9339426530059427 value_1 0.19209505105391145 value_2 value_4
0.1829111168626696 value_1 0.3859590762294829 value_3 0.49506685859523714 value_1 value_4
0.4649922652170062 value_4 0.2388197456020862 value_1 0.5821930731181055 value_3 value_2
0.7056975984014571 value_3 0.7912561448756605 value_2 0.583445193246007 value_2 value_1
0.7020725801121444 value_2 0.30402703885920346 value_3 0.04503019689582288 value_1 value_3
0.972873926628381 value_4 0.49790456565096974 value_2 0.5351506322622299 value_3 value_2
0.9800272663123906 value_4 0.7857549584005028 value_2 0.7845342156942934 value_2 value_2
0.3849116126075387 value_4 0.575401195557788 value_3 0.30851125018671155 value_2 value_1
0.307205474935472 value_4 0.6624222220852971 value_3 0.16863097250461578 value_2 value_4
0.35339167388156056 value_3 0.8257101406343281 value_3 0.42974784155376256 value_2 value_2
0.23176977783441544 value_3 0.4140687526669353 value_3 0.9215692698489875 value_4 value_1
0.0029222716111689806 value_3 0.3131722614634782 value_3 0.5687908811960369 value_2 value_3
0.04286101181060076 value_3 0.5007404908537865 value_2 0.43881698441691697 value_4 value_3
0.6103670832235366 value_1 0.7940549736376852 value_3 0.9781869775615633 value_3 value_2
0.16963966167531908 value_3 0.04383513401262462 value_2 0.26489853486418724 value_1 value_3
0.05906890705227852 value_2 0.1590251310262829 value_1 0.3514371367637068 value_2 value_1
0.3409382733516395 value_4 0.37021428579464555 value_1 0.47316515096463263 value_1 value_2
0.2183145103044808 value_2 0.6201830499339849 value_4 0.4175027667079121 value_3 value_3
0.37452042987570167 value_3 0.8869362093973905 value_3 0.9536087405867875 value_3 value_4
0.4409519403707236 value_3 0.19724191562272608 value_2 0.06293099350295961 value_3 value_3
0.2102779084816575 value_2 0.3786265719681978 value_3 0.530836578225717 value_4 value_2
0.29873897484503686 value_2 0.998199513880536 value_3 0.942711598938331 value_1 value_1
0.3139732195995748 value_3 0.5170114845968783 value_3 0.40251253894530237 value_2 value_2
0.7120097447186708 value_3 0.8344084317795932 value_2 0.16717897588387132 value_2 value_3
0.27749142283573747 value_2 0.04601348121650517 value_3 0.3604996183421463 value_3 value_3
0.8522745280060917 value_2 0.19428613828495145 value_4 0.4210331302601844 value_2 value_4
0.33606668026186526 value_2 0.6655481320340186 value_4 0.029589938698336482 value_3 value_4
0.5626148171722889 value_1 0.8179685671348125 value_4 0.41476235049776733 value_2 value_2
0.30742508824914694 value_4 0.0007749286014586687 value_1 0.20578541001304984 value_2 value_3
0.32709991419687867 value_3 0.9094477160833776 value_2 0.6376898866146803 value_2 value_3
0.5137795377522707 value_3 0.2204506613779813 value_3 0.15573537908494473 value_1 value_2
0.6405913627240807 value_3 0.7442238254006952 value_2 0.22001316002570093 value_3 value_3
0.03311859769746661 value_2 0.3327314162161201 value_4 0.07593094045296311 value_2 value_2
0.6727676002774388 value_4 0.10762157198041677 value_3 0.6390477488748729 value_1 value_1
0.8075837912037969 value_3 0.12177854566834867 value_3 0.10325888567604125 value_4 value_1
0.33615517476573586 value_4 0.8199897718150169 value_2 0.7075568044092506 value_2 value_2
0.25877783237956464 value_3 0.9591271656099707 value_2 0.18249404150992632 value_1 value_4
0.00031156744807958603 value_3 0.6191650584805757 value_3 0.5523874722421169 value_3 value_4
0.12538991239853203 value_4 0.616821707226336 value_3 0.8344000466167927 value_2 value_1
0.2485654519405216 value_2 0.4281584557611495 value_3 0.26489256671629846 value_4 value_4
0.6550800281111151 value_2 0.6508767465129495 value_1 0.9012983755674213 value_2 value_3
0.8550778937060386 value_1 0.42115971981547773 value_3 0.4806739422492683 value_3 value_2
0.16213938756845891 value_2 0.23060628911480308 value_4 0.4139083737973124 value_3 value_1
0.39965259633027017 value_3 0.21063022944144905 value_3 0.48324313201010227 value_3 value_3
0.9275483798701316 value_3 0.33913975208997726 value_3 0.3842884097248316 value_3 value_1
0.9085133941844106 value_2 0.153881968697533 value_2 0.6463061550166458 value_4 value_1
0.9621329833753407 value_2 0.3347969220485538 value_2 0.264816184528172 value_2 value_3
0.938007663236931 value_2 0.48801479139365256 value_4 0.7644482261966914 value_4 value_2
0.8811793019995093 value_2 0.06920670974068344 value_3 0.8112403394188732 value_3 value_4
0.9772389158606529 value_3 0.7288073145318776 value_3 0.7834482982289046 value_3 value_3
0.7284396691247821 value_4 0.45360462414100766 value_3 0.3106421909760684 value_4 value_3
0.15640628524124622 value_1 0.36489871283993125 value_1 0.8474098844453692 value_3 value_1
0.07819984154775739 value_3 0.4256272988859564 value_1 0.24850684241391718 value_3 value_3
0.570201460737735 value_3 0.8237658485304564 value_3 0.19917085906490684 value_4 value_4
0.3998743232805282 value_4 0.6754945020657033 value_2 0.6197483520954847 value_4 value_4
0.017662838101387024 value_3 0.8288593243341893 value_2 0.5354627200867981 value_2 value_4
0.7971603395417333 value_4 0.9838989556301385 value_3 0.7396506499499083 value_4 value_1
0.2503055853303522 value_1 0.5311194115784019 value_4 0.557149717817083 value_3 value_2
0.2864234736189246 value_2 0.8648688874673098 value_3 0.6078097028657794 value_4 value_1
0.7354567172005773 value_1 0.33392596151679754 value_3 0.8605078579857945 value_1 value_4
0.36076088389381766 value_3 0.5213415361940861 value_3 0.28642618632875383 value_2 value_3
0.04113236046396196 value_3 0.21107967989519238 value_4 0.47646311298012733 value_3 value_3
0.32393325003795326 value_3 0.9937811715062708 value_4 0.3705701583530754 value_2 value_3
0.1991380276158452 value_2 0.4208125399891287 value_2 0.5988087130244821 value_2 value_3
0.052114965626969934 value_3 0.480062301736325 value_3 0.4368777363561094 value_1 value_2
0.6609651083126664 value_2 0.009574094321578741 value_3 0.5499960235320032 value_2 value_1
0.8070182383526117 value_2 0.4673769155051559 value_4 0.3570390064269304 value_2 value_2
0.6942306193523109 value_1 0.6440303949639201 value_4 0.9989222916774452 value_3 value_2
0.9001837589312345 value_2 0.508091707713902 value_4 0.6324517424218357 value_2 value_1
0.6497392172459513 value_3 0.9816023998428136 value_2 0.53098787763156 value_3 value_2
0.6714485175907612 value_2 0.9292036893311888 value_3 0.3980019355658442 value_1 value_4
0.43296967004425824 value_3 0.36070049507543445 value_2 0.03700409037992358 value_2 value_2
0.2178127020597458 value_1 0.5379584766924381 value_2 0.39143962459638715 value_3 value_3
0.6967872926034033 value_1 0.023578362772241235 value_1 0.9789317359682173 value_1 value_3
0.8197010830044746 value_2 0.41000268724747 value_1 0.5027262179646641 value_1 value_3
0.8642233845312148 value_4 0.019681174540892243 value_4 0.5661088323686272 value_1 value_4
0.9692180098500103 value_1 0.04121863981708884 value_1 0.4830814569722861 value_4 value_2
0.03315133252181113 value_3 0.17335979850031435 value_3 0.9001371769700199 value_3 value_2
0.7395086728502065 value_2 0.05144210183061659 value_3 0.23055537114851177 value_4 value_3
0.43171988148242235 value_1 0.46966692176647484 value_1 0.20981703675352037 value_4 value_3
0.10890416521579027 value_3 0.45412024506367743 value_4 0.5188205763697624 value_2 value_2
0.41088381106965244 value_1 0.8476952358614653 value_4 0.8632996596861631 value_2 value_4
0.8698908293154091 value_2 0.5881430311128497 value_1 0.18241334590129554 value_3 value_4
0.3074261494912207 value_1 0.9810748777817935 value_3 0.9625921337865293 value_3 value_4
0.9526266537141055 value_1 0.696424420690164 value_2 0.3006916483864188 value_3 value_3
0.5163500448688865 value_3 0.016283433185890317 value_3 0.855393974808976 value_4 value_3
0.09455373324453831 value_3 0.839824756141752 value_1 0.289932148065418 value_2 value_3
0.3350528124719858 value_2 0.6893793086055666 value_3 0.5730140435043722 value_3 value_2
0.13544889842160046 value_1 0.42378153232857585 value_3 0.6452697122003883 value_2 value_3
0.01819392736069858 value_1 0.7472616955637932 value_1 0.9923379665706307 value_3 value_2
0.5297429142519832 value_2 0.40930006513372064 value_3 0.0631711301393807 value_4 value_1
0.6654081970918924 value_2 0.9660306975711137 value_2 0.6734853982925415 value_4 value_3
0.043035494862124324 value_4 0.538877631071955 value_4 0.5825451777782291 value_2 value_3
0.25841663172468543 value_2 0.9142617462202907 value_2 0.819379371823743 value_2 value_1
0.7268535338807851 value_1 0.9284629779867828 value_1 0.7825640900991857 value_3 value_2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--
This gist is based on those three gists:
http://bl.ocks.org/mbostock/1341021
http://bl.ocks.org/jasondavies/1341281
http://bl.ocks.org/syntagmatic/4020926
-->
<title>Parallel Coordinates Ordinal Axis</title>
<style>
svg {
font: 10px sans-serif;
}
.background path {
fill: none;
stroke: #ddd;
shape-rendering: crispEdges;
}
.foreground path {
fill: none;
stroke: steelblue;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
cursor: move;
}
.axis .axis-label {
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 50, right: 50, bottom: 50, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var dimensions = [
{
name: "column1",
scale: d3.scale.linear().range([height, 0]),
type: "number"
},
{
name: "column2",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: "string"
},
{
name: "column3",
scale: d3.scale.linear().range([height, 0]),
type: "number"
},
{
name: "column4",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: "string"
},
{
name: "column5",
scale: d3.scale.linear().range([height, 0]),
type: "number"
},
{
name: "column6",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: "string"
},
{
name: "column7",
scale: d3.scale.ordinal().rangePoints([0, height]),
type: "string"
}
];
var x = d3.scale.ordinal().domain(dimensions.map(function(d) { return d.name; })).rangePoints([0, width]),
y = {},
dragging = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(error, data) {
//Create the dimensions depending on attribute "type" (number|string)
//The x-scale calculates the position by attribute dimensions[x].name
dimensions.forEach(function(dimension) {
dimension.scale.domain(dimension.type === "number"
? d3.extent(data, function(d) { return +d[dimension.name]; })
: data.map(function(d) { return d[dimension.name]; }).sort());
});
// Add grey background lines for context.
background = svg.append("g")
.attr("class", "background")
.selectAll("path")
.data(data)
.enter().append("path")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(data)
.enter().append("path")
.attr("d", path);
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d.name) + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return {x: x(d.name)}; })
.on("dragstart", function(d) {
dragging[d.name] = x(d.name);
background.attr("visibility", "hidden");
})
.on("drag", function(d) {
dragging[d.name] = Math.min(width, Math.max(0, d3.event.x));
foreground.attr("d", path);
dimensions.sort(function(a, b) { return position(a) - position(b); });
x.domain(dimensions.map(function(d) { return d.name; }));
g.attr("transform", function(d) { return "translate(" + position(d) + ")"; })
})
.on("dragend", function(d) {
delete dragging[d.name];
transition(d3.select(this)).attr("transform", "translate(" + x(d.name) + ")");
transition(foreground).attr("d", path);
background
.attr("d", path)
.transition()
.delay(500)
.duration(0)
.attr("visibility", null);
})
);
// Add an axis and title.
g.append("g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(axis.scale(d.scale)); })
.append("text")
.style("text-anchor", "middle")
.attr("class", "axis-label")
.attr("y", -19)
.text(function(d) { return d.name; });
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(d.scale.brush = d3.svg.brush().y(d.scale).on("brushstart", brushstart).on("brush", brush));
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
});
function position(d) {
var v = dragging[d.name];
return v == null ? x(d.name) : v;
}
function transition(g) {
return g.transition().duration(500);
}
// Returns the path for a given data point.
function path(d) {
//return line(dimensions.map(function(p) { return [position(p), y[p](d[p])]; }));
return line(dimensions.map(function(dimension) {
var v = dragging[dimension.name];
var tx = v == null ? x(dimension.name) : v;
return [tx, dimension.scale(d[dimension.name])];
}));
}
function brushstart() {
d3.event.sourceEvent.stopPropagation();
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) { return !p.scale.brush.empty(); }),
extents = actives.map(function(p) { return p.scale.brush.extent(); });
foreground.style("display", function(d) {
return actives.every(function(p, i) {
if(p.type==="number"){
return extents[i][0] <= parseFloat(d[p.name]) && parseFloat(d[p.name]) <= extents[i][1];
}else{
return extents[i][0] <= p.scale(d[p.name]) && p.scale(d[p.name]) <= extents[i][1];
}
}) ? null : "none";
});
}
</script>
</body>
</html>
@Abhijeet-Das
Copy link

Hello,
Can you please share something similar in d3 v4 ? Like the one in this link , I am looking for brushing in the "name" column.
http://plnkr.co/edit/TiM6ZsvMTTBhh8ZdMoFQ?p=preview

Thanks and Regards
Abhijeet

@kbclingen
Copy link

It would be interesting to combine the mouseover and the brush tool, so you could hover over a row and also brush.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment