Skip to content

Instantly share code, notes, and snippets.

Created September 24, 2017 20:05
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 anonymous/4204fc305e2da66c464ac663f96262e6 to your computer and use it in GitHub Desktop.
Save anonymous/4204fc305e2da66c464ac663f96262e6 to your computer and use it in GitHub Desktop.
Mini Charts
license: mit
group year amount1 amount2 amount3
ABC 2010 11124 50.236 0.558825264
ABC 2011 11433 51.577 0.589679841
ABC 2012 11914 49.006 0.583857484
ABC 2013 11734 48.706 0.571516204
ABC 2014 12222 50.496 0.617162112
ABC 2015 11943 52.802 0.630614286
XYZ 2010 13349 51.241 0.68401611
XYZ 2011 11204 56.735 0.63565894
XYZ 2012 10603 40.675 0.43127703
XYZ 2013 9387 44.81 0.42063147
XYZ 2014 10144 59.08 0.59930752
XYZ 2015 11226 44.354 0.497918
Total 2010 12248 50.437 0.61775238
Total 2011 11313 52.609 0.59516562
Total 2012 11319 47.34 0.53584146
Total 2013 10609 47.927 0.50845754
Total 2014 11102 52.213 0.57966873
Total 2015 11616 51.112 0.59371699
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css'>
<style>
body {
margin: 0;position:fixed;top:0;right:0;bottom:0;left:0;
font-family: 'Montserrat', sans-serif;
font-size: 14px;
}
div {
display: inline;
margin: 20px 0px 0px 20px;
}
.spark {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.point {
fill: steelblue;
stroke: #fff;
stroke-width: 3px;
}
.label,
.change,
.axis,
.main {
text-anchor: middle;
alignment-baseline: middle;
fill: #aaa;
}
.change,
.main {
text-anchor: middle;
alignment-baseline: middle;
fill: #333;
}
line.axis {
stroke: #aaa;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<script>
console.clear();
var changeFormat = d3.format(".1f"),
numberFormat = d3.format(",.0f");
d3.csv("data.csv", function(raw){
var data_ABC = raw.filter(function(d){ return d.group == "ABC"}),
data_XYZ = raw.filter(function(d){ return d.group == "XYZ"}),
data_Total = raw.filter(function(d){ return d.group == "Total"});
var miniChart1 = miniChart()
.xValue(function(d){ return +d.year; })
.yValue(function(d){ return +d.amount1; })
.numberFormat(d3.format(",.0f"));
var miniChart2 = miniChart()
.xValue(function(d){ return +d.year; })
.yValue(function(d){ return +d.amount2; })
.numberFormat(d3.format(".2f"));
var miniChart3 = miniChart()
.xValue(function(d){ return +d.year; })
.yValue(function(d){ return +d.amount3; })
.numberFormat(d3.format(".1%"));
d3.select("body").append("div")
.datum(data_ABC)
.call(miniChart1);
d3.select("body").append("div")
.datum(data_ABC)
.call(miniChart2);
d3.select("body").append("div")
.datum(data_ABC)
.call(miniChart3);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniChart1);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniChart2);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniChart3);
d3.select("body").append("div")
.datum(data_Total)
.call(miniChart1);
d3.select("body").append("div")
.datum(data_Total)
.call(miniChart2);
d3.select("body").append("div")
.datum(data_Total)
.call(miniChart3);
});
function dataPrep(raw, xValue, yValue) {
var rough = [{x: NaN, y: NaN}];
//console.log("rough 1",rough);
raw.forEach(function(d, i, data){
rough.push({
x: xValue(d, i, data),
y: yValue(d, i, data)
});
});
//console.log("rough 2", rough);
var dataPairs = d3.pairs(rough);
//console.log("dataPairs",dataPairs)
var data = dataPairs.map(function(d){
var d0 = d[0],
d1 = d[1];
d1.y_delta = (d1.y / d0.y) - 1;
return d1;
});
//console.log("data 3",data);
return data;
}
function miniChart() {
var margin = {top: 20, bottom: 80, left: 80, right: 20},
height = 170 - margin.top - margin.bottom, // default height
width = 280 - margin.left - margin.right, // default width
changeFormat = d3.format(".1f"),
numberFormat = d3.format(",.0f"),
xValue = function(d, i){ return i; },
yValue = function(d, i){ return i; },
xScale = d3.scalePoint(),
yScale = d3.scaleLinear(),
line = d3.line()
.x(function(d, i, data){ return xScale(d.x); })
.y(function(d, i, data){ return yScale(d.y); });
function chart(selection) {
selection.each(function(raw){
var chartData = dataPrep(raw, xValue, yValue);
console.table(chartData);
var yExt = d3.extent(chartData, function(d){ return d.y; });
xScale
.domain(chartData.map(function(d){ return d.x; }))
.range([0, width]);
yScale
.domain(yExt).nice()
.range([height, 0]);
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([chartData]);
// Otherwise, create the skeletal chart.
var svgEnter = svg.enter().append("svg")
svgEnter.append("g").append("g").attr("class", "y axis");
// Update the outer dimensions.
svg = svgEnter.merge(svg)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
/*
svg.insert("rect")
.attr("fill", "#ddd")
.attr("opacity", 0.2)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.insert("rect")
.attr("fill", "#aaa")
.attr("opacity", 0.2)
.attr("x", margin.left)
.attr("y", margin.top)
.attr("width", width)
.attr("height", height);
*/
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update the Y Axis
var yAxis = g.select(".y.axis")
.attr("transform", "translate(" + (-margin.left / 2) + "," + 0 + ")");
// Update the lines
var spark = g.append("path").datum(chartData)
.attr("class", "spark")
.attr("d", line);
// Update the points
var points = g.selectAll("circle.point").data(chartData);
points.enter()
.append("circle").attr("class", "point")
.merge(points)
.attr("cx", function(d, i, data){ return xScale(d.x); })
.attr("cy", function(d, i, data){ return yScale(d.y); })
.attr("r", 5)
var labels = svg.selectAll("text.label").data(chartData);
labels.enter()
.append("text").attr("class", "label")
.merge(labels)
.text(function(d){ return d.x; })
.attr("transform", "translate(" + margin.left + "," +
(height+margin.top) + ")")
.attr("x", function(d){ return xScale(d.x); })
.attr("y", 20)
var changes = svg.selectAll("text.change")
.data(chartData.filter(function(d){ return !isNaN(d.y_delta); }));
changes.enter()
.append("text").attr("class", "change")
.merge(changes)
.text(function(d){ return changeFormat(d.y_delta * 100); })
.attr("transform", "translate(" + margin.left + "," +
(height+margin.top) + ")")
.attr("x", function(d){ return xScale(d.x); })
.attr("y", 40)
yAxis.append("text").attr("class", "axis max")
.text(numberFormat(yExt[1]))
.attr("y", yScale(yExt[1]));
yAxis.append("line").attr("class", "axis")
.attr("x1", 0)
.attr("y1", yScale(yExt[1]) + 10)
.attr("x2", 0)
.attr("y2", yScale(yExt[0]) - 10);
yAxis.append("text").attr("class", "axis min")
.text(numberFormat(yExt[0]))
.attr("y", yScale(yExt[0]));
svg.append("text").text("YOY % Chg").attr("class", "main")
.attr("transform", "translate(" + 0 + "," + (height+margin.top) + ")")
.attr("x", 50)
.attr("y", 40);
});
}
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.xValue = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.yValue = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
chart.numberFormat = function(_) {
if (!arguments.length) return numberFormat;
numberFormat = _;
return chart;
};
chart.changeFormat = function(_) {
if (!arguments.length) return changeFormat;
changeFormat = _;
return chart;
};
return chart;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment