Skip to content

Instantly share code, notes, and snippets.

@natemiller
Last active December 14, 2015 20:38
Show Gist options
  • Save natemiller/119c49ffc4f159fd49ce to your computer and use it in GitHub Desktop.
Save natemiller/119c49ffc4f159fd49ce to your computer and use it in GitHub Desktop.
Selectable Scatterplot

I'm playing with this code adapted largely from the very nice example from http://2011.12devsofxmas.co.uk/2012/01/data-visualisation/

The code remains a bit messy, as I am clearing out parts that I don't need and organizing the remaining code, so please bear with any slight disorganization.

This is best viewed by clicking the link to open this example in a new window so you can see the whole visualization.

site temp pH x y treatment
1 30 7.2 10 50 1
1 25 8 10 35 1
1 25 7.2 15 70 2
2 30 7.2 20 20 2
2 30 8 25 55 3
2 25 8 30 30 3
3 25 7.6 50 100 4
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1">
<title>Data visualisation demo</title>
<style>
body
{
background-color: #ffffff;
font-family: sans-serif;
color: #7c7273;
font-size: 10px;
}
ul
{
list-style-type: none;
margin: 0;
padding: 0;
}
div
{
float: left;
width: 200px;
}
.axis text
{
fill: #7c7273;
}
.axis .domain
{
opacity: 0;
}
.tick
{
stroke: #7c7273;
}
</style>
</head>
<body>
<h1>Visualising Data</h1>
<svg id="visualisation" width="800" height="600"></svg>
<form id="controls">
<div>
<h2>X axis</h2>
<ul id="x-axis">
<li><label><input checked="checked" type="radio" name="x-axis" value="site">Site</label></li>
<li><label><input type="radio" name="x-axis" value="pH">pH Values</label></li>
<li><label><input type="radio" name="x-axis" value="temp">Temperature</label></li>
<li><label><input type="radio" name="x-axis" value="x">X-Value</label></li>
<li><label><input type="radio" name="x-axis" value="y">Y-Value</label></li>
<li><label><input type="radio" name="x-axis" value="treatment">Treatment</label></li>
</ul>
</div>
<div>
<h2>Y axis</h2>
<ul id="y-axis">
<li><label><input checked="checked" type="radio" name="y-axis" value="site">Site</label></li>
<li><label><input type="radio" name="y-axis" value="pH">pH Values</label></li>
<li><label><input checked="checked" type="radio" name="y-axis" value="temp">Temperature</label></li>
<li><label><input type="radio" name="y-axis" value="x">X-Value</label></li>
<li><label><input type="radio" name="y-axis" value="y">Y-Value</label></li>
<li><label><input type="radio" name="y-axis" value="treatment">Treatment</label></li>
</ul>
</div>
<div>
<h2>Radius</h2>
<ul id="r-axis">
<li><label><input checked="checked" type="radio" name="r-axis" value="site">Site</label></li>
<li><label><input checked="checked" type="radio" name="r-axis" value="pH">pH Values</label></li>
<li><label><input type="radio" name="r-axis" value="temp">Temperature</label></li>
<li><label><input type="radio" name="r-axis" value="x">X-Value</label></li>
<li><label><input type="radio" name="r-axis" value="y">Y-Value</label></li>
<li><label><input type="radio" name="r-axis" value="treatment">Treatment</label></li>
</ul>
</div>
<div>
<h2>Dataset</h2>
<ul>
<li>
<select id="dataset">
<option value="errordata">Test Data</option>
</select>
</li>
</ul>
</div>
</form>
</body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="test.js"></script>
</html>
var WIDTH = 800, // width of the graph
HEIGHT = 550, // height of the graph
MARGINS = {top: 20, right: 20, bottom: 20, left: 60}, // margins around the graph
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]), // x range function
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]), // y range function
rRange = d3.scale.linear().range([5, 20]), // radius range function - ensures the radius is between 5 and 20
colours = [
"#1f77b4",
"#ff7f0e",
"#2ca02c",
"#d62728",
"#9467bd",
"#8c564b",
"#e377c2",
"#7f7f7f",
"#bcbd22",
"#17becf"
],
currentDataset,// name of the current data set. Used to track when the dataset changes
data,
xAxis = d3.svg.axis().scale(xRange).tickSize(16).tickSubdivide(true), // x axis function
yAxis = d3.svg.axis().scale(yRange).tickSize(10).orient("right").tickSubdivide(true), // y axis function
vis; // visualisation selection
// runs once when the visualisation loads
function init () {
vis = d3.select("#visualisation");
// add in the x axis
vis.append("g") // container element
.attr("class", "x axis") // so we can style it with CSS
.attr("transform", "translate(0," + HEIGHT + ")") // move into position
.call(xAxis); // add to the visualisation
// add in the y axis
vis.append("g") // container element
.attr("class", "y axis") // so we can style it with CSS
.call(yAxis); // add to the visualisation
// load data, process it and draw it
d3.csv("errordata.csv", function(data) {
rawData = data;
currentDataset = dataset;
redraw();
});
}
// this redraws the graph based on the data in the drawingData variable
function redraw () {
var plot = vis.selectAll ("circle").data(rawData), // select the data points and set their data
axes = getAxes (); // object containing the axes we'd like to use (duration, inversions, etc.)
// add new points if they're needed
plot.enter()
.insert("circle")
.attr("cx", function (d) { return xRange (d[axes.xAxis]); })
.attr("cy", function (d) { return yRange (d[axes.yAxis]); })
.style("opacity", .5)
.style("fill", function (d) { return colours[d.site]; }); // set fill colour from the colours array
// the data domains or desired axes might have changed, so update them all
xRange.domain([
d3.min(rawData, function (d) { return +d[axes.xAxis]; }),
d3.max(rawData, function (d) { return +d[axes.xAxis]; })
]);
yRange.domain([
d3.min(rawData, function (d) { return +d[axes.yAxis]; }),
d3.max(rawData, function (d) { return +d[axes.yAxis]; })
]);
rRange.domain([
d3.min(rawData, function (d) { return +d[axes.radiusAxis]; }),
d3.max(rawData, function (d) { return +d[axes.radiusAxis]; })
]);
// transition function for the axes
var t = vis.transition().duration(1500).ease("exp-in-out");
t.select(".x.axis").call(xAxis);
t.select(".y.axis").call(yAxis);
// transition the points
plot.transition().duration(1500).ease("exp-in-out")
.style("opacity", 0.5)
.style("fill", function (d) { return colours[d.site]; }) // set fill colour from the colours array
.attr("r", function(d) { return rRange (d[axes.radiusAxis]); })
.attr("cx", function (d) { return xRange (d[axes.xAxis]); })
.attr("cy", function (d) { return yRange (d[axes.yAxis]); });
// remove points if we don't need them anymore
plot.exit()
.transition().duration(1500).ease("exp-in-out")
.attr("cx", function (d) { return xRange (d[axes.xAxis]); })
.attr("cy", function (d) { return yRange (d[axes.yAxis]); })
.style("opacity", 0.5)
.attr("r", 0)
.remove();
}
// let's kick it all off!
init ();
//////////////////////////////////////////////////////////
// helper functions - health warning! LOTS of javascript!
//////////////////////////////////////////////////////////
// return the name of the dataset which is currently selected
function getChosenDataset () {
var select = document.getElementById("dataset");
return select.options[select.selectedIndex].value;
}
// return an object containing the currently selected axis choices
function getAxes () {
var x = document.querySelector("#x-axis input:checked").value,
y = document.querySelector("#y-axis input:checked").value,
r = document.querySelector("#r-axis input:checked").value;
return {
xAxis: x,
yAxis: y,
radiusAxis: r
};
}
// called every time a form field has changed
function update () {
var dataset = getChosenDataset(), // filename of the chosen dataset csv
rawData; // the data while will be visualised
// if the dataset has changed from last time, load the new csv file
if (dataset != currentDataset) {
d3.csv("errordata.csv", function (data) {
// process new data and store it in the appropriate variables
currentDataset = dataset;
rawData = data;
redraw();
});
} else {
// process data based on the form fields and store it in the appropriate variables
rawData = data;
redraw();
}
}
// listen to the form fields changing
document.getElementById("dataset").addEventListener ("change", update, false);
document.getElementById("controls").addEventListener ("click", update, false);
document.getElementById("controls").addEventListener ("keyup", update, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment