Published
Edited
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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more