Published
Edited
May 5, 2019
Insert cell
md`# GoT character death in books`
Insert cell
d3v5 = require("https://d3js.org/d3.v5.min.js")
Insert cell
d3 = require("https://d3js.org/d3.v4.min.js")
Insert cell
sample_data = d3v5.csv('https://raw.githubusercontent.com/cse512-19s/A3-visualization-of-GOT-character-death/master/docs/character-deaths-simplify.csv?token=AJUZNUYVU5UOANDM3CRTMGS42SWCU')
Insert cell
html`<style>
<meta charset="utf-8">

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 {
fill:black;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
pre {
width: 100%;
height: 300px;
margin: 6px 12px;
tab-size: 40;
font-size: 10px;
overflow: auto;
}
</style>`
Insert cell
GenderDomain =[0,1]
Insert cell
color={
const maleColor = "#008BFF"
const femaleColor = "#FF3342"
return d3v5.scaleOrdinal().range([femaleColor,maleColor,]).domain(GenderDomain);
}
Insert cell
function unique(array) {
return array.filter((v,i)=> array.indexOf(v) == i)
}
Insert cell
NMDomain = sample_data.map(row => row.Name).sort(d3.ascending)
Insert cell
ALGDomain = unique(sample_data.map(row => row.Allegiances)).sort(d3.ascending)
Insert cell
function ff(x) {
return ALGDomain(x)
}
Insert cell
DYDomain = unique(sample_data.map(row => row['Death Year'])).sort(d3.ascending)
Insert cell
m1=d3.scalePoint()
.range([DYDomain.lenth,0])
.domain(DYDomain)
Insert cell
DCDomain = unique(sample_data.map(row => row['Death Chapter'])).sort(function(a, b){return a - b});
Insert cell
NobDomain= [0,1]
Insert cell
AppDomain=["GoT","CoK","SoS","FfC","DwD"]
Insert cell
output = { const pre = document.createElement("pre"); return pre; }
Insert cell
parallel_coordinates = {
var margin = {top: 50, right: 50, bottom: 100, left: 50};
var width = 1100 - margin.left - margin.right;
var height =1000 - margin.top - margin.bottom;

var x = d3.scalePoint().range([0, width]).padding(1),
y = {},
dragging= {};

var line = d3.line(),
axis = d3.axisLeft(),
background,
foreground;
var dimensions = null;
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 + ")");
// .slice(0,25)
var out = d3.select(output)
out.text(d3.tsvFormat(sample_data));
// Extract the list of dimensions and create a scale for each.
x.domain(dimensions = d3.keys(sample_data[0]).filter(function(d) {
return (y['Name']=d3.scalePoint()
.range([height,0])
.domain(NMDomain)) && d!="Book Intro Chapter" && d!="Gender" && /*(y['Allegiances']=d3.scaleLinear()
.range([height,0])
.domain([0,ALGDomain.length])).map(ff) */
(y['Allegiances']=d3.scalePoint()
.range([height,0])
.domain(ALGDomain))&& d!="GoT" && d!="CoK"&& d!="SoS" && d!="FfC" && d!="DwD" &&(y['Death Year']=d3.scalePoint()
.range([height,0])
.domain(DYDomain)) && (y[d] = d3.scaleLinear()
.domain(d3.extent(sample_data, function(p) { return +p[d]; }))
.range([height, 0]));
}));

// 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)
.attr('stroke',d=>color(d.Gender));

// Add a group element for each dimension.
function position(d) {
var v = dragging[d];
return v == null ? x(d) : v;
}

function transition(g) {
return g.transition().duration(500);
}
const g = svg_adjusted.selectAll(".dimension")
.data(dimensions)
.enter()
.append("g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d) + ")"; })
.call(d3.drag()
.subject(function(d) { return {x: x(d)}; })
.on("start", function(d) {
dragging[d] = x(d);
background.attr("visibility", "hidden");
})
.on("drag", function(d) {
dragging[d] = 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);
g.attr("transform", function(d) { return "translate(" + position(d) + ")"; })
})
.on("end", function(d) {
delete dragging[d];
transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
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(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,-10], [10,height+10]])
.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) {
return actives.every(function(active) {
let result = active.extent[1] <= d[active.dimension] && d[active.dimension] <= active.extent[0];
if(result)selected.push(d);
return result;
}) ? null : "none";
});
(actives.length>0)? out.text(d3.tsvFormat(selected)):out.text(d3.tsvFormat(sample_data));;
}
function updatepath(){
var str=document.getElementById("searchid").value;
const filteredData= sample_data.filter(row => issubstr(row, str));
foreground.selectAll("path").data(filteredData).transition('update').style("display",null)
}
return svg.node();
}
Insert cell
Insert cell
function issubstr(row,str){
if (row['Name'].toUpperCase().includes(str.toUpperCase())) {
return true
}else{
return false
}
}
Insert cell
issubstr (sample_data[0],"frey")
Insert cell
"as s tark".toUpperCase().includes("Stark".toUpperCase())
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