Published
Edited
Nov 19, 2018
1 fork
2 stars
Insert cell
Insert cell
Insert cell
data = d3.csv("https://raw.githubusercontent.com/howwegettonext/2017databreaches/master/breach_level_index.csv")

Insert cell
Insert cell
data.filter(breach => breach.location == "United Kingdom")
Insert cell
Insert cell
data.filter(breach => breach.location == "United Kingdom")
.map(breach => breach.organisation)
Insert cell
Insert cell
d3.format(",") // Format with thousands
(data.map(breach => breach.records = +breach.records) // Get an array of the records
.reduce((total, records) => total + records)) // Reduce them to a total
Insert cell
Insert cell
avgLeaksPerInd = {
let output = []; // Create an empty array
for (let industry of [...new Set(data.map(breach => breach.industry))]) { // For each unique industry
let toPush = {};
toPush["Industry"] = industry;
let leaks = data.filter(breach => breach.industry == industry) // Filter for that industry
.map(breach => breach.records = +breach.records) // Convert array of strings to integers
// Average the array
toPush["Average Leaks"] = leaks.reduce((total, records) => (total + records))/leaks.length;
toPush["n"] = leaks.length; // How many leaks in each category
output.push(toPush);
}
// Sort the output from highest leaks to lowest
output.sort((a, b) => b["Average Leaks"] - a["Average Leaks"]);
return output;
}
Insert cell
Insert cell
table_keys = Object.keys(avgLeaksPerInd[0])
Insert cell
table = {
// Set up the header, using the keys from above
let header = table_keys[0] + "|" + table_keys[1] + "|" + table_keys[2] + "\n-|-|-\n"
// Create an empty body, ready to be filled by the loop
let body = ""
// Loop over all the things in avgLeaksPerInd
for (let item of avgLeaksPerInd) {
let line = ""; // empty line, ready to be added to
line += item[table_keys[0]]; // Add the industry
line += "|"; // Add a pipe spacer
line += d3.format(",.0f")(item[table_keys[1]]); // Add the average leaks
line += "|"; // Add a pipe spacer
line += d3.format(",.0f")(item[table_keys[2]]); // Add the number of leaks
line += "\n"; // Add newline character
body += line; // Add the line we just created to the body
}
// Then glue the header to the body and return it in markdown format.
return md`${header + body}`
}
Insert cell
Insert cell
cleaned = data.filter(breach => breach.organisation != "River City Media") // Exclude River City Media
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
x = d3.scaleBand() // Band scales are used for categorical data
.domain(clean_avgLeaksPerInd.map(d => d["Industry"])) // Domain is industry list
.range([margin.left, width - margin.right]) // Range is horizontal chart space
.padding(0.1) // A little padding - 10% of a bar width
Insert cell
y = d3.scaleLinear() // A linear scale for the y-values
.domain([0, d3.max(clean_avgLeaksPerInd, d => d["Average Leaks"])]).nice() // Domain from 0 to max data
.range([height - margin.bottom, margin.top]) // Range from bottom to top of chart
Insert cell
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`) // Move it to the bottom
.call(d3.axisBottom(x) // Draw it...
.tickSize(0).tickPadding(8)) // ...without the individual tick marks
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`) // Move it to the left
.call(d3.axisLeft(y)) // Draw it...
.call(g => g.select(".domain").remove()) // ...without the axis line
Insert cell
Insert cell
height = 500
Insert cell
margin = ({top: 20, right: 0, bottom: 30, left: 70})
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height)); // Create an svg
// The next bit is a normal D3 data join
// See https://bost.ocks.org/mike/join/ for details
svg.append("g")
.selectAll("rect")
.data(clean_avgLeaksPerInd)
.enter()
.append("rect")
.attr("x", d => x(d["Industry"]))
.attr("y", d => y(d["Average Leaks"]))
.attr("height", d => y(0) - y(d["Average Leaks"]))
.attr("width", x.bandwidth())
.attr("fill", // Double encoding the records with height and colour
d => d3.scaleSequential(d3.interpolateBlues).domain([-5000000, 26000000])
(d["Average Leaks"]));
svg.append("g")
.call(xAxis); // Add the x axis
svg.append("g")
.call(yAxis); // Add the y axis
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("https://d3js.org/d3.v5.js")
Insert cell
Insert cell
Insert cell
html`<style>table {max-width: 100%}</style>`
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