Skip to content

Instantly share code, notes, and snippets.

@stevekinney
Last active August 29, 2015 13:57
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 stevekinney/9791596 to your computer and use it in GitHub Desktop.
Save stevekinney/9791596 to your computer and use it in GitHub Desktop.
Take a set of values and get the raw materials for making a Lorenz Curve.
var lorenz = function (data) {
// Sort the data in ascending order.
data = data.sort(function (a,b) {
return d3.ascending(a, b);
});
// Divide into quintiles.
// - Create an array of five empty sub-arrays.
var quintiles = Array.apply(null, new Array(5)).map(function () { return []; });
// - Create a scale and put each value in the right sub-array by its index.
var scale = d3.scale.quantize()
.domain([0, data.length])
.range(d3.range(0,5));
data.forEach(function (datum, index) {
quintiles[scale(index)].push(datum);
});
// Get the total for each quintile.
return quintiles.map(function (quintile) {
return d3.sum(quintile);
})
// Calculate the percent of total income in each quintile.
.map(function (quintile) {
return quintile / d3.sum(data);
})
// Calculate the cumulative percentage of household income.
.map(function (quintile, index, data) {
return quintile + d3.sum(data.slice(0, index));
});
};
var d = [1,2,3,4,5,6,7,8,9,10,11,12,13,18,20];
var lorenz = function (data) {
// Sort the data in ascending order.
data = data.sort(function (a,b) {
return d3.ascending(a, b);
});
// Divide into quintiles.
// - Create an array of five empty sub-arrays.
var quintiles = Array.apply(null, new Array(5)).map(function () { return []; });
// - Create a scale and put each value in the right sub-array by its index.
var scale = d3.scale.quantize().domain([0, data.length]).range(d3.range(0,5));
data.forEach(function (datum, index) {
quintiles[scale(index)].push(datum);
});
// Get the total for each quintile.
return quintiles.map(function (quintile) {
return d3.sum(quintile);
})
// Calculate the percent of total income in each quintile.
.map(function (quintile) {
return quintile / d3.sum(data);
})
// Calculate the cumulative percentage of household income.
.map(function (quintile, index, data) {
return quintile + d3.sum(data.slice(0, index));
});
};
var lorenzify = function () {
return Array.prototype.slice.call(arguments).map(function (data) {
return lorenz(data);
});
};
var dataset = lorenz(d);
function lorenzCurve(options) {
var dataset = options.data;
var colors = options.colors || [
'#F00', '#0F0', '#00F', '#F0F'
];
var ci = 0;
var width = options.height || 500;
var height = options.weight || 250;
var margin = options.margin || 45;
var svg = d3.select(options.el || '#chart')
.append('svg')
.attr({
width: width,
height: height
});
var xScale = d3.scale.ordinal()
.domain(d3.range(5))
.rangeBands([0, width - (margin * 2)], 1, 0);
var yScale = d3.scale.linear()
.range([height - (margin * 2), 0]);
var line = d3.svg.line()
.x(function(d,i) { return xScale(i); })
.y(function(d,i) { return yScale(d); });
dataset.forEach(function (d) {
svg.append('path')
.datum(d)
.attr('fill', 'none')
.attr('stroke', colors[ci++])
.attr('d', line)
.attr('transform', 'translate(' + margin + ',' + margin + ')');
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left')
.ticks(5)
.tickFormat(function(d) { return d * 100 + '%'; });
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(' + (margin * 0.9) + ',' + margin + ')')
.call(yAxis);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(5);
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(' + margin + ',' + (height - margin * 0.9) + ')')
.call(xAxis);
return svg;
}
lorenzCurve({ data: [dataset] });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment