Skip to content

Instantly share code, notes, and snippets.

@curran
Last active September 26, 2015 21:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save curran/1fb2ae1dfc1471972904 to your computer and use it in GitHub Desktop.
Save curran/1fb2ae1dfc1471972904 to your computer and use it in GitHub Desktop.
Reusable Scatter Plot

A reusable D3 scatter plot, constructed using Towards Reusable Charts and Standalone Scatter Plot as inspiration.

In the original reusable charts example, the comments state

// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.

In this adaptation, a simplifying assumption was made that no nondeterministic accessors will be given. Going one step further, an assumption was made that accessors will only want to access specific "columns" of data, meaning properties on each row object.

web counter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Reusable Scatterplot Example</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<link href="http://fonts.googleapis.com/css?family=Poiret+One" rel="stylesheet" type="text/css">
<style>
/* Make the container flush against the upper left corner. */
body {
margin: 0px;
}
/* Put a border around SVG elements so we can see how big they are. */
svg {
border-style: solid;
border-width: 1px;
}
/* Style the X and Y axes. */
.axis text {
font-family: "Poiret One", cursive;
font-size: 16pt;
}
.axis .label {
font-size: 32pt;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
<script src="scatterPlot.js"></script>
<script src="main.js"></script>
<script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-66108038-1', 'auto'); ga('send', 'pageview'); </script>
</body>
</html>
sepal_length sepal_width petal_length petal_width species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa
4.6 3.4 1.4 0.3 setosa
5.0 3.4 1.5 0.2 setosa
4.4 2.9 1.4 0.2 setosa
4.9 3.1 1.5 0.1 setosa
5.4 3.7 1.5 0.2 setosa
4.8 3.4 1.6 0.2 setosa
4.8 3.0 1.4 0.1 setosa
4.3 3.0 1.1 0.1 setosa
5.8 4.0 1.2 0.2 setosa
5.7 4.4 1.5 0.4 setosa
5.4 3.9 1.3 0.4 setosa
5.1 3.5 1.4 0.3 setosa
5.7 3.8 1.7 0.3 setosa
5.1 3.8 1.5 0.3 setosa
5.4 3.4 1.7 0.2 setosa
5.1 3.7 1.5 0.4 setosa
4.6 3.6 1.0 0.2 setosa
5.1 3.3 1.7 0.5 setosa
4.8 3.4 1.9 0.2 setosa
5.0 3.0 1.6 0.2 setosa
5.0 3.4 1.6 0.4 setosa
5.2 3.5 1.5 0.2 setosa
5.2 3.4 1.4 0.2 setosa
4.7 3.2 1.6 0.2 setosa
4.8 3.1 1.6 0.2 setosa
5.4 3.4 1.5 0.4 setosa
5.2 4.1 1.5 0.1 setosa
5.5 4.2 1.4 0.2 setosa
4.9 3.1 1.5 0.1 setosa
5.0 3.2 1.2 0.2 setosa
5.5 3.5 1.3 0.2 setosa
4.9 3.1 1.5 0.1 setosa
4.4 3.0 1.3 0.2 setosa
5.1 3.4 1.5 0.2 setosa
5.0 3.5 1.3 0.3 setosa
4.5 2.3 1.3 0.3 setosa
4.4 3.2 1.3 0.2 setosa
5.0 3.5 1.6 0.6 setosa
5.1 3.8 1.9 0.4 setosa
4.8 3.0 1.4 0.3 setosa
5.1 3.8 1.6 0.2 setosa
4.6 3.2 1.4 0.2 setosa
5.3 3.7 1.5 0.2 setosa
5.0 3.3 1.4 0.2 setosa
7.0 3.2 4.7 1.4 versicolor
6.4 3.2 4.5 1.5 versicolor
6.9 3.1 4.9 1.5 versicolor
5.5 2.3 4.0 1.3 versicolor
6.5 2.8 4.6 1.5 versicolor
5.7 2.8 4.5 1.3 versicolor
6.3 3.3 4.7 1.6 versicolor
4.9 2.4 3.3 1.0 versicolor
6.6 2.9 4.6 1.3 versicolor
5.2 2.7 3.9 1.4 versicolor
5.0 2.0 3.5 1.0 versicolor
5.9 3.0 4.2 1.5 versicolor
6.0 2.2 4.0 1.0 versicolor
6.1 2.9 4.7 1.4 versicolor
5.6 2.9 3.6 1.3 versicolor
6.7 3.1 4.4 1.4 versicolor
5.6 3.0 4.5 1.5 versicolor
5.8 2.7 4.1 1.0 versicolor
6.2 2.2 4.5 1.5 versicolor
5.6 2.5 3.9 1.1 versicolor
5.9 3.2 4.8 1.8 versicolor
6.1 2.8 4.0 1.3 versicolor
6.3 2.5 4.9 1.5 versicolor
6.1 2.8 4.7 1.2 versicolor
6.4 2.9 4.3 1.3 versicolor
6.6 3.0 4.4 1.4 versicolor
6.8 2.8 4.8 1.4 versicolor
6.7 3.0 5.0 1.7 versicolor
6.0 2.9 4.5 1.5 versicolor
5.7 2.6 3.5 1.0 versicolor
5.5 2.4 3.8 1.1 versicolor
5.5 2.4 3.7 1.0 versicolor
5.8 2.7 3.9 1.2 versicolor
6.0 2.7 5.1 1.6 versicolor
5.4 3.0 4.5 1.5 versicolor
6.0 3.4 4.5 1.6 versicolor
6.7 3.1 4.7 1.5 versicolor
6.3 2.3 4.4 1.3 versicolor
5.6 3.0 4.1 1.3 versicolor
5.5 2.5 4.0 1.3 versicolor
5.5 2.6 4.4 1.2 versicolor
6.1 3.0 4.6 1.4 versicolor
5.8 2.6 4.0 1.2 versicolor
5.0 2.3 3.3 1.0 versicolor
5.6 2.7 4.2 1.3 versicolor
5.7 3.0 4.2 1.2 versicolor
5.7 2.9 4.2 1.3 versicolor
6.2 2.9 4.3 1.3 versicolor
5.1 2.5 3.0 1.1 versicolor
5.7 2.8 4.1 1.3 versicolor
6.3 3.3 6.0 2.5 virginica
5.8 2.7 5.1 1.9 virginica
7.1 3.0 5.9 2.1 virginica
6.3 2.9 5.6 1.8 virginica
6.5 3.0 5.8 2.2 virginica
7.6 3.0 6.6 2.1 virginica
4.9 2.5 4.5 1.7 virginica
7.3 2.9 6.3 1.8 virginica
6.7 2.5 5.8 1.8 virginica
7.2 3.6 6.1 2.5 virginica
6.5 3.2 5.1 2.0 virginica
6.4 2.7 5.3 1.9 virginica
6.8 3.0 5.5 2.1 virginica
5.7 2.5 5.0 2.0 virginica
5.8 2.8 5.1 2.4 virginica
6.4 3.2 5.3 2.3 virginica
6.5 3.0 5.5 1.8 virginica
7.7 3.8 6.7 2.2 virginica
7.7 2.6 6.9 2.3 virginica
6.0 2.2 5.0 1.5 virginica
6.9 3.2 5.7 2.3 virginica
5.6 2.8 4.9 2.0 virginica
7.7 2.8 6.7 2.0 virginica
6.3 2.7 4.9 1.8 virginica
6.7 3.3 5.7 2.1 virginica
7.2 3.2 6.0 1.8 virginica
6.2 2.8 4.8 1.8 virginica
6.1 3.0 4.9 1.8 virginica
6.4 2.8 5.6 2.1 virginica
7.2 3.0 5.8 1.6 virginica
7.4 2.8 6.1 1.9 virginica
7.9 3.8 6.4 2.0 virginica
6.4 2.8 5.6 2.2 virginica
6.3 2.8 5.1 1.5 virginica
6.1 2.6 5.6 1.4 virginica
7.7 3.0 6.1 2.3 virginica
6.3 3.4 5.6 2.4 virginica
6.4 3.1 5.5 1.8 virginica
6.0 3.0 4.8 1.8 virginica
6.9 3.1 5.4 2.1 virginica
6.7 3.1 5.6 2.4 virginica
6.9 3.1 5.1 2.3 virginica
5.8 2.7 5.1 1.9 virginica
6.8 3.2 5.9 2.3 virginica
6.7 3.3 5.7 2.5 virginica
6.7 3.0 5.2 2.3 virginica
6.3 2.5 5.0 1.9 virginica
6.5 3.0 5.2 2.0 virginica
6.2 3.4 5.4 2.3 virginica
5.9 3.0 5.1 1.8 virginica
var scatterPlot = ScatterPlot();
scatterPlot
.outerWidth(960)
.outerHeight(500)
.margin({ left: 95, top: 5, right: 10, bottom: 85 })
.xColumn("sepal_length")
.xAxisLabel("Sepal Length (cm)")
.xAxisLabelOffset(70)
.xTicks(20)
.yColumn("petal_length")
.yAxisLabel("Petal Length (cm)")
.yAxisLabelOffset(50)
.yTicks(20)
.colorColumn("species")
.rColumn("sepal_width")// "r" stands for radius
.rMin(2)
.rMax(13)
.colorRange(["#00c65c", "#8400c6", "#e54100"]);
function type(d){
d.sepal_length = +d.sepal_length;
d.sepal_width = +d.sepal_width;
d.petal_length = +d.petal_length;
d.petal_width = +d.petal_width;
return d;
}
d3.csv("iris.csv", type, function (data){
d3.select("#chart")
.datum(data)
.call(scatterPlot);
});
function ScatterPlot(){
var outerWidth = 100;
var outerHeight = 100;
var margin = { left: 60, top: 5, right: 10, bottom: 60 };
var rMin = 2; // "r" stands for radius
var rMax = 300;
var xColumn = "No X column configured";
var yColumn = "No Y column configured";
var rColumn = "No radius column configured";
var colorColumn = "No color column configured";
var colorRange = d3.scale.category10().range();
var xAxisLabel = "No X axis label configured";
var xAxisLabelOffset = 40;
var yAxisLabel = "No Y axis label configured";
var yAxisLabelOffset = 30;
var xScale = d3.scale.linear();
var yScale = d3.scale.linear();
var rScale = d3.scale.linear();
var colorScale = d3.scale.ordinal();
var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
.tickFormat(d3.format("s"))
.outerTickSize(0);
var xTicks = 5;
var yAxis = d3.svg.axis().scale(yScale).orient("left")
.tickFormat(d3.format("s"))
.outerTickSize(0);
var yTicks = 5;
function chart(selection){
var innerWidth = outerWidth - margin.left - margin.right;
var innerHeight = outerHeight - margin.top - margin.bottom;
colorScale.range(colorRange);
xScale.range([0, innerWidth]);
yScale.range([innerHeight, 0]);
rScale.range([rMin, rMax]);
xAxis.ticks(xTicks);
yAxis.ticks(yTicks);
selection.each(function (data) {
var svg = d3.select(this).selectAll("svg").data([data]);
var gEnter = svg.enter().append("svg").append("g");
var g = svg.select("g");
var circles = g.selectAll("circle").data(data);
gEnter
.append("g")
.attr("class", "x axis")
.append("text")
.attr("class", "label")
.style("text-anchor", "middle");
gEnter
.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "label")
.style("text-anchor", "middle");
xScale.domain(d3.extent(data, function (d){ return d[xColumn]; }));
yScale.domain(d3.extent(data, function (d){ return d[yColumn]; }));
rScale.domain(d3.extent(data, function (d){ return d[rColumn]; }));
svg
.attr("width", outerWidth)
.attr("height", outerHeight);
g.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g
.select(".x.axis")
.attr("transform", "translate(0," + innerHeight + ")")
.call(xAxis)
.select("text")
.attr("x", innerWidth / 2)
.attr("y", xAxisLabelOffset)
.text(xAxisLabel);
g
.select(".y.axis")
.call(yAxis)
.select("text")
.attr("transform", "translate(-" + yAxisLabelOffset + "," + (innerHeight / 2) + ") rotate(-90)")
.text(yAxisLabel);
circles.enter().append("circle");
circles
.attr("cx", function (d){ return xScale(d[xColumn]); })
.attr("cy", function (d){ return yScale(d[yColumn]); })
.attr("r", function (d){ return rScale(d[rColumn]); })
.attr("fill", function (d){ return colorScale(d[colorColumn]); });
circles.exit().remove();
});
}
chart.outerWidth = function(_) {
if (!arguments.length) return outerWidth;
outerWidth = _;
return chart;
};
chart.outerHeight = function(_) {
if (!arguments.length) return outerHeight;
outerHeight = _;
return chart;
};
chart.xColumn = function(_) {
if (!arguments.length) return xColumn;
xColumn = _;
return chart;
};
chart.yColumn = function(_) {
if (!arguments.length) return yColumn;
yColumn = _;
return chart;
};
chart.rColumn = function(_) {
if (!arguments.length) return rColumn;
rColumn = _;
return chart;
};
chart.rMin = function(_) {
if (!arguments.length) return rMin;
rMin = _;
return chart;
};
chart.rMax = function(_) {
if (!arguments.length) return rMax;
rMax = _;
return chart;
};
chart.colorRange = function(_) {
if (!arguments.length) return colorRange;
colorRange = _;
return chart;
};
chart.colorColumn = function(_) {
if (!arguments.length) return colorColumn;
colorColumn = _;
return chart;
};
chart.xAxisLabel = function(_) {
if (!arguments.length) return xAxisLabel;
xAxisLabel = _;
return chart;
};
chart.yAxisLabel = function(_) {
if (!arguments.length) return yAxisLabel;
yAxisLabel = _;
return chart;
};
chart.xAxisLabelOffset = function(_) {
if (!arguments.length) return xAxisLabelOffset;
xAxisLabelOffset = _;
return chart;
};
chart.yAxisLabelOffset = function(_) {
if (!arguments.length) return yAxisLabelOffset;
yAxisLabelOffset = _;
return chart;
};
chart.xTicks = function(_) {
if (!arguments.length) return xTicks;
xTicks = _;
return chart;
};
chart.yTicks = function(_) {
if (!arguments.length) return yTicks;
yTicks = _;
return chart;
};
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
return chart;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment