Dataviz Course 2018 - GiovanniDw/frontend-data GitHub Wiki

Data Visualization Course 2018

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

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