Skip to content

Instantly share code, notes, and snippets.

@SpaceActuary
Last active February 12, 2018 19:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpaceActuary/55842603594b91865f7740e731f1bbd7 to your computer and use it in GitHub Desktop.
Save SpaceActuary/55842603594b91865f7740e731f1bbd7 to your computer and use it in GitHub Desktop.
Mini Tables
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;
display: flex;
flex-wrap: wrap
}
body > div {
flex: 0 0 30%;
margin: 20px 0px 0px 20px;
}
table {
font-family: 'Montserrat', sans-serif;
font-size: 14px;
}
table thead tr th{
border-bottom: 1px solid black;
}
.label,
.change,
.axis,
.main {
text-anchor: middle;
alignment-baseline: middle;
fill: #aaa;
}
th.textual,
td.textual {
text-align: left;
}
th.centered,
td.centered {
text-align: center;
}
th.numeric,
td.numeric {
text-align: right;
}
.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(".2f"),
numberFormat = d3.format(",.0f"),
percentFormat = d3.format(".1%");
d3.csv("data.csv", function(data){
data.forEach(function(d, i, data){
var d0 = i ? data[i-1] : {};
d.year = +d.year;
d.amount1 = +d.amount1;
d.yoy1 = i ? d.amount1 / d0.amount1 - 1 : 0;
d.amount2 = +d.amount2;
d.yoy2 = i ? d.amount2 / d0.amount2 - 1 : 0;
d.amount3 = +d.amount3;
d.yoy3 = i ? d.amount3 / d0.amount3 - 1 : 0;
})
var data_ABC = data.filter(function(d){ return d.group == "ABC"}),
data_XYZ = data.filter(function(d){ return d.group == "XYZ"}),
data_Total = data.filter(function(d){ return d.group == "Total"});
var miniTable0 = miniTable()
.columns([
{ head: 'Year', cl: 'textual', thead_row: 1, rowspan: 2, colspan: 1,
html: function(d){ return d.year; } },
{ head: 'Variable 1', cl: 'centered', thead_row: 1, rowspan: 1, colspan: 2 },
{ head: 'Variable 2', cl: 'centered', thead_row: 1, rowspan: 1, colspan: 2 },
{ head: 'Variable 3', cl: 'centered', thead_row: 1, rowspan: 1, colspan: 2 },
{ head: 'Amount', cl: 'numeric', thead_row: 2,
html: function(d){ return numberFormat(+d.amount1); } },
{ head: 'YoY%', cl: 'numeric', thead_row: 2,
html: function(d){ return percentFormat(+d.yoy1); } },
{ head: 'Amount', cl: 'numeric', thead_row: 2,
html: function(d){ return changeFormat(+d.amount2); } },
{ head: 'YoY%', cl: 'numeric', thead_row: 2,
html: function(d){ return percentFormat(+d.yoy2); } },
{ head: 'Amount', cl: 'numeric', thead_row: 2,
html: function(d){ return percentFormat(+d.amount3); } },
{ head: 'YoY%', cl: 'numeric', thead_row: 2,
html: function(d){ return percentFormat(+d.yoy3); } }
]);
var miniTable1 = miniTable()
.columns([
{ head: 'Year', cl: 'textual',
html: function(d){ return d.year; } },
{ head: 'Amount', cl: 'numeric',
html: function(d){ return numberFormat(+d.amount1); } },
{ head: 'YoY%', cl: 'numeric',
html: function(d){ return percentFormat(+d.yoy1); } }
]);
var miniTable2 = miniTable()
.columns([
{ head: 'Year', cl: 'textual',
html: function(d){ return d.year; } },
{ head: 'Amount', cl: 'numeric',
html: function(d){ return changeFormat(+d.amount2); } },
{ head: 'YoY%', cl: 'numeric',
html: function(d){ return percentFormat(+d.yoy2); } }
]);
var miniTable3 = miniTable()
.columns([
{ head: 'Year', cl: 'textual',
html: function(d){ return d.year; } },
{ head: 'Amount', cl: 'numeric',
html: function(d){ return percentFormat(+d.amount3); } },
{ head: 'YoY%', cl: 'numeric',
html: function(d){ return percentFormat(+d.yoy3); } }
]);
d3.select("body").append("div")
.datum(data_ABC)
.call(miniTable0);
/*
d3.select("body").append("div")
.datum(data_ABC)
.call(miniTable1);
d3.select("body").append("div")
.datum(data_ABC)
.call(miniTable2);
d3.select("body").append("div")
.datum(data_ABC)
.call(miniTable3);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniTable1);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniTable2);
d3.select("body").append("div")
.datum(data_XYZ)
.call(miniTable3);
d3.select("body").append("div")
.datum(data_Total)
.call(miniTable1);
d3.select("body").append("div")
.datum(data_Total)
.call(miniTable2);
d3.select("body").append("div")
.datum(data_Total)
.call(miniTable3);
*/
});
function miniTable() {
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"),
columns = [],
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 table(selection) {
selection.each(function(data){
var tableData = data; // dataPrep(raw, xValue, yValue);
console.table(tableData);
var yExt = d3.extent(tableData, d => d.y);
// Select the svg element, if it exists.
var tableElement = d3.select(this).selectAll("table").data([1]);
// Otherwise, create the skeletal chart.
var tableElementEnter = tableElement.enter().append("table")
tableElementEnter.append("thead")
tableElementEnter.append("tbody")
tableElementEnter.append("tfoot")
tableElement = tableElement.merge(tableElementEnter)
var thead = tableElement.selectAll("thead")
var tbody = tableElement.selectAll("tbody")
var tfoot = tableElement.selectAll("tfoot")
var thead_data = d3.nest()
.key(function (d) { return d.thead_row; })
.entries(columns);
console.log("thead_data",thead_data)
var thead_tr = thead.selectAll('th').data(thead_data)
thead_tr.enter().append("tr")
.merge(thead_tr)
.selectAll('th')
.data(function(d){ return d.values}).enter()
.append('th')
.attr('class', d => d.cl)
.attr('rowspan', d => d.rowspan)
.attr('colspan', d => d.colspan)
.text(d => d.head)
var rows = tbody.selectAll("tr")
.data(tableData)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row, i) {
// evaluate column objects against the current row
return columns.filter(function(c){ return ('html' in c) })
.map(function(c) {
var cell = {};
d3.keys(c).forEach(function(k) {
cell[k] = typeof c[k] == 'function' ? c[k](row,i) : c[k];
});
return cell;
});
});
cells.enter().append("td")
.merge(cells)
.html(d => d.html)
.attr('class', d => d.cl)
})
}
table.width = function(_) {
if (!arguments.length) return width;
width = _;
return table;
};
table.height = function(_) {
if (!arguments.length) return height;
height = _;
return table;
};
table.columns = function(_) {
if (!arguments.length) return columns;
columns = _;
return table;
};
table.numberFormat = function(_) {
if (!arguments.length) return numberFormat;
numberFormat = _;
return table;
};
table.changeFormat = function(_) {
if (!arguments.length) return changeFormat;
changeFormat = _;
return table;
};
return table;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment