Dataviz Course 2018 - GiovanniDw/frontend-applications GitHub Wiki

Data Visualization Course 2018

https://curran.github.io/dataviz-course-2018/

Table of Contents

Intro to Javascript 2018

Input

index.js

import { getCars } from './getCars';
import { generateReport } from './generateReport';

document.getElementById('message-element').textContent = 'Loading...';

getCars().then((cars) => {
	const message = generateReport(cars, 2000);
	document.getElementById('message-element').textContent = message;
});

getCars.js

const carsJSON = `[
  {
    "year": 2000,
    "make": "Honda",
    "model": "Accord",
    "price": 2800
  },
  {
    "make": "Nissan",
    "model": "Leaf",
    "year": 2012,
    "price": 1800
  },
  {
    "make": "Ford",
    "model": "F150",
    "year": 2009,
    "price": 1950
  },
  {
    "make": "Chevrolet",
    "model": "Trailblazer",
    "year": 2009,
    "price": 1550
  },
  {
    "make": "Honda",
    "model": "Pilot",
    "year": 2003,
    "price": 2200
  }
]`;
const cars = JSON.parse(carsJSON);

export const getCars = () =>
	new Promise((resolve) => {
		setTimeout(() => resolve(cars), 2000);
	});

generateReport.js

import { formatCar } from './formatCar';

export const generateReport = (cars, maxPrice) =>
	cars
		.filter((car) => car.price < maxPrice)
		.map(formatCar)
		.join('\n');

formatCar.js

export const formatCar = (car) => {
	const { year, make, model, price } = car;

	return `${year} ${make} ${model}: $$${price}`;
};

Output

2012 Nissan Leaf: $1800
2009 Ford F150: $1950
2009 Chevrolet Trailblazer: $1550

Inputs for Data Visualization

Dataset Types

dataset-types

Attribute Types

attr-types

Special Cases

Special Cases

Making a Bar Chart

Representing a data table in javascript

const svg = select('svg');

const width = +svg.attr('width');
const height = +svg.attr('height');

csv('./static/data/Provincies_PenR.csv').then((data) => {
	data.forEach((d) => {
		d.PenR = +d.PenR;
	});
	render(data);
});

Creating rectangles for each row

const xScale = scaleLinear()
	.domain([0, max(data, xValue)])
	.range([0, innerWidth]);

const yScale = scaleBand()
	.domain(data.map(yValue))
	.range([0, innerHeight])
	.padding(0.2);

Using linear and band scales

const xScale = scaleLinear()
	.domain([0, max(data, xValue)])
	.range([0, innerWidth]);

const yScale = scaleBand()
	.domain(data.map(yValue))
	.range([0, innerHeight])
	.padding(0.2);

The margin convention

const margin = { top: 20, right: 50, bottom: 20, left: 100 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;

Adding Axes

const yAxis = axisLeft(yScale);
yAxis(g.append('g'));

=

const yAxis = axisLeft(yScale);
g.append('g').call(yAxis);
g.append('g').call(axisLeft(yScale));

Uploading Datasets

Data Table Summary

import { select, csv, csvFormat } from 'd3';

const kilobytes = (data) => Math.ceil(csvFormat(data).length / 1024);

const body = select('body');

csv('data.csv').then((data) => {
	body.append('pre').text(
		[
			`${data.length} rows`,
			`${Object.keys(data[0]).length} columns`,
			`${kilobytes(data)} KB`,
		].join(', ')
	);

	body.append('pre').text('First 10 rows:');

	body.append('pre').text(JSON.stringify(data.slice(0, 10), null, 2));
});

Auto MPG Summary

import { select, csv, csvFormat } from 'd3';

const kilobytes = (data) => Math.ceil(csvFormat(data).length / 1000);

const body = select('body');

csv('https://vizhub.com/curran/datasets/auto-mpg.csv').then((data) => {
	body.append('pre').text(
		[
			`${data.length} rows`,
			`${Object.keys(data[0]).length} columns`,
			`${kilobytes(data)} kB`,
		].join(', ')
	);

	body.append('pre').text('First 10 rows:');

	body.append('pre').text(JSON.stringify(data.slice(0, 10), null, 2));
});

Customizing Axes of a Bar Chart with D3.js

Formatting Numbers

bl.ocks.org/mstanaland/6106487

Starting number: 1500

d3.format(",") : 1,500

d3.format(".1f") : 1500.0

d3.format(",.2f") : 1,500.00

d3.format("s") : 1.5k

d3.format(".1s") : 2k

d3.format(".2s") : 1.5k

function(d) { return "$" + d3.format(",.2f")(d); } : $1,500.00

d3.format(",.2%") : 150,000.00%

Removing unnecessary lines

g.append('g').call(axisLeft(yScale)).selectAll('.domain, .tick line').remove();

Adding a visualization title

g.append('text').attr('y', -5).text('PenR Capaciteit Profincies');

Adding axis Labels

const xAxisG = g
	.append('g')
	.call(xAxis)
	.attr('transform', `translate(0,${innerHeight})`);

xAxisG.select('.domain').remove();

xAxisG
	.append('text')
	.attr('y', 40)
	.attr('x', innerWidth / 2)
	.attr('fill', 'black')
	.text('PenR Capaciteit');

Making Tick Grid Lines

xAxisG.append('text').attr('class', 'axis-label');

g.append('text').attr('class', 'title');
.tick text {
	fill: #757575;
}

.tick line {
	stroke: #e0e0e0;
}

.axis-label {
	font-size: 1.2em;
	fill: #757575;
}

.title {
	font-size: 1.5em;
	fill: #424242;
}

Making Scatter Plot

import {
	select,
	csv,
	scaleLinear,
	extent,
	scalePoint,
	axisLeft,
	axisBottom,
	format,
	text,
} from 'd3';

const svg = select('svg');

const width = +svg.attr('width');
const height = +svg.attr('height');

// d.capacity = +d.capacity;
// d.minimumHeightInMeters = +d.minimumHeightInMeters;
// d.openingTimes = +d.openingTimes;
// d.id = +d.id;

const render = (data) => {
	const title = 'Capaciteit Vs Heights';

	const xValue = (d) => d.capacity;
	const xAxisLabel = 'Capaciteit';

	const yValue = (d) => d.minimumHeightInMeters;
	const circleRadius = 10;
	const yAxisLabel = 'Min Hoogte';

	const margin = { top: 50, right: 50, bottom: 50, left: 100 };
	const innerWidth = width - margin.left - margin.right;
	const innerHeight = height - margin.top - margin.bottom;

	const xScale = scaleLinear()
		.domain(extent(data, xValue))
		.range([0, innerWidth])
		.nice();

	const yScale = scaleLinear()
		.domain(extent(data, yValue))
		.range([innerHeight, 0])
		.nice();

	const g = svg
		.append('g')
		.attr('transform', `translate(${margin.left},${margin.top})`);

	const xAxis = axisBottom(xScale).tickSize(-innerHeight).tickPadding(15);

	const yAxis = axisLeft(yScale).tickSize(-innerWidth).tickPadding(10);

	const yAxisG = g.append('g').call(yAxis);
	yAxisG.selectAll('.domain').remove();

	yAxisG
		.append('text')
		.attr('class', 'axis-label')
		.attr('y', -93)
		.attr('x', -innerHeight / 2)
		.attr('fill', 'black')
		.attr('transform', `rotate(-90)`)
		.attr('text-anchor', 'middle')
		.text(yAxisLabel);

	const xAxisG = g
		.append('g')
		.call(xAxis)
		.attr('transform', `translate(0,${innerHeight})`);

	xAxisG.select('.domain').remove();

	xAxisG
		.append('text')
		.attr('class', 'axis-label')
		.attr('y', 40)
		.attr('x', innerWidth / 2)
		.attr('fill', 'black')
		.text(xAxisLabel);

	g.selectAll('circle')
		.data(data)
		.enter()
		.append('circle')
		.attr('cy', (d) => yScale(yValue(d)))
		.attr('cx', (d) => xScale(xValue(d)))
		.attr('r', circleRadius);

	g.append('text').attr('class', 'title').attr('y', -5).text(title);
};

csv('./static/data/OpenParking_PnR.csv').then((data) => {
	data.forEach((d) => {
		d.capacity = +d.capacity;
		d.minimumHeightInMeters = +d.minimumHeightInMeters;
		d.openingTimes = +d.openingTimes;
		d.id = +d.id;
	});
	console.log(data);
	render(data);
});

World map with d3js

⚠️ **GitHub.com Fallback** ⚠️