Coursera: Information Visualization D3.js Project Week 1 & Week 2
Tags: JavaScript, D3js

Photo by Lukas Blazek on Unsplash

I’ve been learning much about D3 and its usefulness this past week. In the course so far I was able to do week 1 with no problem since it was just a JavaScript refresher course. For the week 2 curriculum, I learned about writing the code to create bar charts and label the x and y axis with information being passed down from a csv file with multiple columns of information. The assignment from this course is to gradually add more lines of code to the index.html in order to come up with a stunning and visually appealing data charts for Airlines. Week 1’s assignment was just creating the border display for the two charts and CSS styling for the header. Week 2 was getting into the weeds of things such as defining the height and width for the bars, defining the scale along the x and y axis, and drawing the overall bar chart.

So starting within the index.html file, we need to add the following within our <head>:

<script src=”d3.js”></script>

In other script tag I created the store object and typed the loadData function o grab the csv file saved within my folder.

let store = {}

function loadData() {

let promise = d3.csv(“routes.csv”)

return promise.then(routes => {

store.routes = routes

return store;

})

}

I iterate over each route which produces a dictionary where the keys are the airline ids and the values are the information of the airline. I then increment the count (which are the number of routes) of the airline and then I save the updated information in the dictionary using the airline id as key.

function groupByAirline(data) {

let result = data.reduce((result, d) => {

let currentData = result[d.AirlineID] || {

“AirlineID”: d.AirlineID,

“AirlineName”: d.AirlineName,

“Count”: 0

}

currentData.Count += 1

result[d.AirlineID] = currentData//TODO: Save the updated information in the dictionary using the airline id as key.

return result;

}, {})

The below continuing code defining result, is used to convert the dictionary produced by the code above, into a list that will make it easier to create the visualization. I then sort the data in descending order of count.

result = Object.keys(result).map(key => result[key])

result.sort((a, b) => {

return d3.descending(a.Count, b.Count)

})

return result

}

The following function will be called showData() and we will need to get the routes from our store variable. Once we get that we will compute the number of routes per airline. Than we will call on our drawAirlinesChart function with airlines as a parameter. That function will be drawing the airlines barchart.

function showData() {

let routes = store.routes

let airlines = groupByAirline(store.routes);

console.log(airlines)

drawAirlinesChart(airlines)

}

loadData().then(showData);

The following code is defining the function getAirlinesChartConfig() in which we will define our chart’s width, height, margin, etc. For our scale we will create the function getAirlinesChartScales(), to draw the bar it is our function drawBarsAirlinesChart(), and lastly for our axes its drawAxesAirlinesChart().

function getAirlinesChartConfig() {

let width = 350;

let height = 400;

let margin = {

top: 10,

bottom: 50,

left: 130,

right: 10

}

let bodyHeight = height — margin.top — margin.bottom

let bodyWidth = width — margin.left — margin.right//TODO: Compute the width of the body by subtracting the left and right margins from the width.

//The container is the SVG where we will draw the chart. In our HTML is the svg ta with the id AirlinesChart.

let container = d3.select(“#AirlinesChart”)

container

.attr(“width”, width)

.attr(“height”, height)

return { width, height, margin, bodyHeight, bodyWidth, container }

}

function getAirlinesChartScales(airlines, config) {

let { bodyWidth, bodyHeight } = config;

let maximunCount = d3.max(airlines.map( d => {

return d.Count

}))Use d3.max to get the highest Count value we have on the airlines list.

console.log(maximunCount)

let xScale = d3.scaleLinear()

.range([0, bodyWidth])

.domain([0, maximunCount])

let yScale = d3.scaleBand()

.range([0, bodyHeight])

.domain(airlines.map(a => a.AirlineName)) //The domain is the list of airlines names

.padding(0.2)

return { xScale, yScale }

}

function drawBarsAirlinesChart(airlines, scales, config) {

let {margin, container} = config; // this is equivalent to ‘let margin = config.margin; let container = config.container’

let {xScale, yScale} = scales

let body = container.append(“g”)

.style(“transform”,

`translate(${margin.left}px,${margin.top}px)`

)

let bars = body.selectAll(“.bar”)

.data(airlines)

bars.enter().append(“rect”)

.attr(“height”, yScale.bandwidth())

.attr(“y”, (d) => yScale(d.AirlineName))

.attr(“width”, (d) => xScale(d.Count))

.attr(“fill”, “#2a5599”)

}

function drawAxesAirlinesChart(airlines, scales, config){

let {xScale, yScale} = scales

let {container, margin, height} = config;

let axisX = d3.axisBottom(xScale)

.ticks(5)

container.append(“g”)

.style(“transform”,

`translate(${margin.left}px,${height — margin.bottom}px)`

)

.call(axisX)

let axisY = d3.axisLeft(yScale)

container.append(“g”)

.style(“transform”,

`translate(${margin.left}px, ${margin.top}px)`

)

.call(axisY)

}

</script>