In the second lab of the Metis data visualization course my group (group 1) was to visualize the 1st example of Anscombe's Quartet. Creating a scatter plot is all well and good, but why not make things a little bit more interesting.
What's more interesting than a scatter plot, you might ask. Well, circle that only reveal their postion when hovered over? No, this does not conform to data visualization best practices, but that's not what I was going for in this example.
You must know the rules, before you can break them.
xxxxxxxxxx
<head>
<meta charset="utf-8">
<style type="text/css">
body {
font-family: avenir, sans;
}
.axis text {
font: 10px avenir;
fill: #777;
}
.axis path {
display: none;
}
.axis line {
stroke-width:1px;
stroke: #ccc;
stroke-dasharray: 2px 2px;
}
.anscombe-group text{
opacity: 0;
pointer-events: none;
}
.anscombe-group:hover text {
opacity: 1;
font: 12px avenir;
}
</style>
</head>
<body>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js" charset="utf-8"></script>
<script>
// D3 margin convention bl.ock https://bl.ocks.org/mbostock/3019563
// define the margin object, clockwise starting from the top
var margin = {top: 20, right: 10, bottom: 20, left: 30};
// define width and height as inner dimensions of the chart
var width = 520 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// define svg and a g element and move it down and to the left
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 +")");
// loading in a tsv from a file in the directory
d3.tsv("quartet.tsv", function(error, data) {
// We need to conver the d.x and d.y to actual numbers
data.forEach(function(d) {
d.x = +d.x;
d.y = +d.y;
});
// Filter the data so that we're only working with Group I
var group1 = data.filter(function(d) {
return d.group == "I";
});
// Create chart components and utilities
var xDomain = [0, + d3.max(group1, function(d) {
return d.x;
})];
// Use d.x for the yDomain to create a square plain
var yDomain = [0, d3.max(group1, function(d) {
return d.x;
})];
var color = d3.scale.linear()
.domain(xDomain)
.range(["white", "blue"]);
var xScale = d3.scale.linear()
.domain(xDomain)
.range([0, width]);
var yScale = d3.scale.linear()
.domain(yDomain)
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize([-height])
.ticks(5)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(-width)
.ticks(5)
.orient("left");
// Add the chart components to the screen
// Add the xAxis g element
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the yAxis g element
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(0,0)" )
.call(yAxis);
// Add the circles to the screen
var group = svg.selectAll("g.anscombe-group")
.data(group1)
.enter().append("g")
.attr("class", "anscombe-group")
.attr("transform", function(d) {
return "translate(" + (xScale(d.x) - 5) + "," + (yScale(d.y) + 5) + ")";
});
// Add marks to the plain
group
.append("circle")
.attr("r", "5")
.attr("fill", function(d) {
return color(d.x);
}) // d3.rgb(0, 114, 200).toString())
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
group
.append("text")
.text(function(d) {
return "(" + d.x.toFixed() + ", " + d.y.toFixed(2) + ")";
})
.attr("transform", "translate(-21, 6)");
// Create the mouse event handlers
function handleMouseOver(d, i) {
d3.select(this)
.attr("fill", d3.rgb(229, 230, 235))
.transition()
.attr("r", "35px");
}
function handleMouseOut(d, i) {
d3.select(this)
.attr("fill", color(d.x))
.transition()
.attr("r", "5");
}
});
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js