Data Visualization using D3.js

tapan awasthi
4 min readApr 20, 2020

--

A Guide to Visualize our data not using Python or R but our beloved JavaScript ❤️

We’ll Be Visualizing our data on a d3.js Grouped Bar Chart visualization.

Our Result Will Look Not Something But Exactly Like This

We’ll be having only 3 files in our project

  • index.html
  • styles.css
  • app.js ( all the code for visualization engine will go here )
  • the dataset obviously in any form ( CSV, tsv, Json etc. ) “dataset.json” here

Let’s start with index.html and later giving it basic styling in styles.css

<!DOCTYPE html><html lang="en"><head>
<link rel="stylesheet" href="styles.css">
</head><body><script src="https://d3js.org/d3.v3.min.js"></script></body></html>

Well that’s pretty much it what all Html will contain, isn’t it too much? 😆

Now let’s talk about giving our output some sassy styling 😉

Here it goes.

body {
font: 15px sans-serif;
width: auto;
background-color: floralwhite;
}
.axis path,
.axis line {
fill: none;
stroke: #f56f6f;
shape-rendering: crispEdges;
}
body {
position: relative;
width: 100%;
display: block;
}
body > * {
margin: auto;
width: 1000px;
height: 100%;
display: block;
overflow: auto;
}
body > script {
display: none
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}

This will do the job of colouring and keeping the graph at the centre.

Now comes the main part of developing our engine.

Writing the app.js file.

var margin = {top: 80, right: 10, bottom: 30, left: 80},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .5);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x0)
.tickSize(0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var color = d3.scale.ordinal()
.range(["#ca0020","#f4a582","#d5d5d5","#92c5de","#0571b0"]);
var svg = d3.select('body').append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

Up till now, we’ve defined our variables defining the size of the graph, scale and other properties like colouring and all.

Now let’s have a look at the dataset we have in the dataset.json file.

[
{
"FarmName" : "Farm 1",
"Values" : [
{
"value": 1.5,
"property": "Nitrate "
},
{
"value": 0.5,
"property": "Ammonia "
},
{
"value": 6.7,
"property": "pH Value"
}
]
},
{
"FarmName" : "Farm 2",
"Values" : [
{
"value": 4.0,
"property": "Nitrate "
},
{
"value": 0.3,
"property": "Ammonia "
},
{
"value": 6.5,
"property": "pH Value"
}
]
},
{
"FarmName" : "Farm 3",
"Values" : [
{
"value": 3.0,
"property": "Nitrate "
},
{
"value": 0.3,
"property": "Ammonia "
},
{
"value": 6.7,
"property": "pH Value"
}
]
},
{
"FarmName" : "Farm 4",
"Values" : [
{
"value": 3.5,
"property": "Nitrate "
},
{
"value": 0.2,
"property": "Ammonia "
},
{
"value": 7.0,
"property": "pH Value"
}
]
},

Now let’s process our data and build the graph bit by bit. 😆

d3.json('/dataset.json', function(error, data) {
if(error){
// handle the error
}
let FarmNames = data.map(function(d) { return d.FarmName; });
let PropertyNames = data[0].Values.map(function(d) { return d.property; });
x0.domain(FarmNames);
x1.domain(PropertyNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(FarmName) { return d3.max(FarmName.Values, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.style('opacity','0')
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.text("Value");
svg.select('.y').transition().duration(500).delay(1300).style('opac ity','1');
var slice = svg.selectAll(".slice")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform",function(d) { return "translate(" + x0(d.FarmName) + ",0)"; });
slice.selectAll("rect")
.data(function(d) { return d.Values; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.property); })
.style("fill", function(d) { return color(d.property) })
.attr("y", function(d) { return y(0); })
.attr("height", function(d) { return height - y(0); })
.on("mouseover", function(d) {
d3.select(this).style("fill", d3.rgb(color(d.property)).darker(2));
})
.on("mouseout", function(d) {
d3.select(this).style("fill", color(d.property));
});
slice.selectAll("rect")
.transition()
.delay(function (d) {return Math.random()*1000;})
.duration(1000)
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
//Legendvar legend = svg.selectAll(".legend")
.data(data[0].Values.map(function(d) { return d.property; }).reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d,i) { return "translate(0," + i * 20 + ")"; })
.style("opacity","0");
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d) { return color(d); });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {return d; });
legend.transition().duration(500).delay(function(d,i){ return 1300 + 100 * i; }).style("opacity","1");
}
})

In this piece of code, we took out .json file and gave it to d3.json() which gave us two things the data itself and an error.

Then we made two arrays using es6 .map(), which includes all the property names and the farm names they belong to.

Then we configured our graph axes and injected the values to it.

And then appended the SVG to the body tag of the Html document so that it can render the graph on the screens.

So that’s all it takes Visualising a dataset using our very own Javascript.

A quick question what you guys think about the capabilities of JavaScript?

It’ll be interesting knowing your views on this in the Response section.

--

--