- d3.js
- JavaScript
- HTML
- CSS
- Webpack
- Travelers to each province in CSV file from Statistics Canada on Jan 2000 - Dec 2019
- Province map Json file from Statistics Canada
- Canadian cities CSV file
Data is the greatest power in the era of big data and AI.
This project aims to show meaninful graphical visualizations intuitively from large volume of complicated data sets. JavaScript and its library d3 are used to express interactively and dynamically.
Data Interpretation is the process of making sense out of a collection of data that has been processed. This collection may be present in various forms like bar graphs, line charts and tabular forms and other similar forms and hence needs an interpretation of some kind.
-
Where was the most popular Canadian province to travel for oversea visitors last 20 Years?
-
Is there any popularity trend change?
-
Are total travelers increasing on each provinces or on the nation?
-
Which month or season are busier than others?
-
Which city is the most visited, on which month ,and in which year?
-
Which graphical chart, form, or method are appropriate to maximize the specific meaning from the the data set provided.
Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation.
Three different scale functions from d3 are used to represent specific needs of visualization forms.
After through observation of data sets over 20 years, visitor amount gaps between most popular and least provinces are were too significant as 0 to about 1.7 million. Threshold scale is selected to represent inbetween cut values directly in colors.
const visitorFormat = [0, 500, 5000, 10000, 50000, 100000, 300000, 700000, 1000000, 1300000, 1700000];
const colorScale = d3.scaleThreshold()
.domain(visitorFormat)
.range(["#ffffff", "#f7fbff", "#e3eef9", "#cfe1f2", "#b5d4e9", "#93c3df", "#6daed5", "#4b97c9", "#2f7ebc", "#1864aa", "#0a4a90", "#08306b"]);
The d3.scaleThreshold()
method is called for the variable colorScale
to group variable visitorFormat
array representing the precise cut values with the appropriate range of blue color intensities.
d3.selectAll('.path')
.data(dataSorted)
.style("fill", function (d) { return colorScale(parseInt(d.VALUE)) })
The colorScale
was used to fill the specific colors for different province regions on the map.
d3.scaleSqrt()
method creates a square-root based scale.
In order to represent such a great gap between the min to max values of real life event visually on the same chart, square-root scale is chosen to lower the larger value and scale up the smaller graphically.
const yScale = d3.scaleSqrt()
.domain([0, 1700000])
.range([0, height]);
const yAxisScale = d3.scaleSqrt()
.domain([1700000, 0])
.range([0, height]);
Variables yScale
and yAxisScale
are declared by calling d3.scaleSqrt()
with its domain and range values.
.attr('y', d => height - yScale(parseInt(d.VALUE)) + 10)
.attr('height', d => yScale(parseInt(d.VALUE)));
canvas1.append('g')
.attr('class', 'y_axis')
.attr('transform', 'translate(65, 10)')
.call(yAxisScale);
yScale
and yAxisScale
are each called to represent the scaled values of the visitor values from the data sets on the bar chart.
For series of categirical unordered data, a linear scale, d3.scaleLinear()
method is used.
const xScale = d3.scaleLinear()
.rangeRound([0, width])
.domain([0, data.length]);
Continuous Linear scale in their domain and range typically produces a piecewise scale for each entry province equally.
Detail informations of each specific data sets on different charts or map graphics are interactively and dynamically presented with JavaScript functions.
//create tooptip element
const mapTooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//listen mouseover event
function onMouseOver(d, i) {
mapTooltip.transition()
.duration(0)
.style("opacity", 0.9);
mapTooltip.html(d.GEO + " on " + d.REF_DATE + "<br/>" + "Tourists from Overseas: " + d.VALUE + " persons")
.style("left", (d3.event.pageX - 100) + "px")
.style("top", (d3.event.pageY - 120) + "px");
}
//listen mouseout event
function onMouseOut(d, i) {
d3.selectAll('div.tooltip').style('opacity', 0);
}
Various parts of the graphics are added with tooltips using
d3.selection.on('action', function(){})
method
d3.selectAll('.path')
.data(dataSorted)
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut);
const monthlyData = [];
for(let ele = 0; ele < data.length; ele ++ ) {
if ((parseInt(data[ele]['REF_DATE'].slice(2, 4)) == year) &&
(parseInt(data[ele]['REF_DATE'].slice(5, 7)) == month))
{
monthlyData.push(data[ele]);
}
if (monthlyData.length == 12 ) { break }
}
Specific narrow-down data parts are collected and organized.
mapChart(monthlyData);
const sortedMonthlyData = [...monthlyData];
sortedMonthlyData.sort(function(b, a){ return parseInt(a.VALUE) - parseInt(b.VALUE)});
const totalVisitor = sortedMonthlyData.reduce((a, b) => (a + parseInt(b.VALUE)), 0);
barChart(sortedMonthlyData);
pieChart(sortedMonthlyData, totalVisitor);
And they are sent through calling map or chart build methods with appropriate data.
const projection = d3.geoMercator()
.scale([410])
.translate([980, 770]);
The 3-D earth was projected on 2d map using d3.geoMercator()
scaling function.
const city = canvas2.selectAll('.cityDots')
.data(cities)
.enter()
.append('circle')
.attr('class', 'cityDots')
.attr('r', 2)
.attr('cx', city =>{
const coords1 = projection([city.lng, city.lat]);
return coords1[0];
})
.attr('cy', city => {
const coords2 = projection([city.lng, city.lat]);
return coords2[1];
});
And the cities latitude and longitude circle points are also needed to be projected through the same funcion.
canvas2.selectAll('.cityName')
.data(cities)
.enter()
.append('text')
.attr('class', 'cityName')
.attr('x', city => {
const coords3 = projection([city.lng, city.lat]);
return coords3[0];
})
.attr('y', city => {
const coords4 = projection([city.lng, city.lat]);
return coords4[1];
})
And the city name labels needed to be applied to the same process
- Further Details on Each Canadian Cities
- Interconnected actions of different charts to each other
- Combine additionally related data sets from other data files
- Develope more insight and meaning from data sets and graphically represent.
- Use other tech tools run concurrently with D3.
- Updating automatically with newly updated data sets from api sources.
- API Reference
MIT © Justin K Lee