Published
Edited
Aug 30, 2019
3 forks
1 star
Insert cell
Insert cell
Insert cell
parallel_coordinates = {
const margin = {top: 30, right: 10, bottom: 10, left: 10};
const width = 960 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;

const svg = d3.select(DOM.svg(width + margin.left + margin.right, height+margin.top + margin.bottom));
const svg_adjusted = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// parallel coord rendering part
const x = d3.scalePoint().range([0, width]).padding(1);
const y = {};
const line = d3.line();
const axis = d3.axisLeft();
let background;
let foreground;

// output of selection
const out = d3.select(output)
out.text(d3.tsvFormat(sample_data.slice(0,24)));
const dimensions_preset = {
support: [0, 1],
aiScore: [0.2, 0.9],
aRatio: [0, 1],
iRatio: [0, 1],
num_of_elements: [1, 7],
};

let dimensions = d3.keys(sample_data[0])
x.domain(dimensions);
dimensions.forEach(d => {
y[d] = d3.scaleLinear()
.domain(dimensions_preset[d] || d3.extent(sample_data, element => +element[d]))
.range([height, 0]);
});

const colorDomain = [0.3, 0.6]; // y[colorDimention].domain() // we should make this the same with network view
const colorDimention = "aiScore";
const lineColor = d => d3.scaleSequential(colorDomain, d3.interpolateRdYlGn)(d[colorDimention]);

// Add grey background lines for context.
background = svg_adjusted.append("g")
.attr("class", "background")
.selectAll("path")
.data(sample_data)
.enter().append("path")
.attr("d", path);

// Add blue foreground lines for focus.
foreground = svg_adjusted.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(sample_data)
.enter().append("path")
.attr("d", path)
.style("stroke", lineColor);

// Add a group element for each dimension.
const g = svg_adjusted.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d) + ")"; });

// Add an axis and title.
g.append("g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(axis.scale(y[d])); })
.append("text")
.style("text-anchor", "middle")
.attr("y", -9)
.text(function(d) { return d; });

// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(y[d].brush = d3.brushY()
.extent([[-10,0], [10,height]])
.on("brush", brush)
.on("end", brush)
)
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);

// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; }));
}

// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = [];
svg.selectAll(".brush")
.filter(function(d) {
y[d].brushSelectionValue = d3.brushSelection(this);
return d3.brushSelection(this);
})
.each(function(d) {
// Get extents of brush along each active selection axis (the Y axes)
actives.push({
dimension: d,
extent: d3.brushSelection(this).map(y[d].invert)
});
});
var selected = [];
// Update foreground to only display selected values
foreground.style("display", function(d) {
let isActive = actives.every(function(active) {
let result = active.extent[1] <= d[active.dimension] && d[active.dimension] <= active.extent[0];
return result;
});
// Only render rows that are active across all selectors
if(isActive) selected.push(d);
return (isActive) ? null : "none";
});
// Render data as asimple grid
(actives.length>0)?out.text(d3.tsvFormat(selected)):out.text(d3.tsvFormat(sample_data));
}
return svg.node();
}
Insert cell
Insert cell
sample_data = d3.json('https://gist.githubusercontent.com/ravengao/343110d5303a6de87049f2f9db1a4daa/raw/9bf74a9d296d2038b746a8ab133a16313dfc1129/pc_supp%253E0.4.json')
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more