Histogram Layout
En esta sección presentaremos el layout para crear histogramas.
Primero, cargamos los datos usando d3.json
(recuerde que es asíncrono):
var datos;
d3.json('/assets/data/food.json', function(error, data) {
if (error) { console.error(error); }
datos = data;
});
Definimos los parámetros del gráfico y la función de acceso:
var marginBottom = 40,
marginLeft = 20,
width = 800 - marginLeft,
height = 600 - marginBottom;
var value = function(d) { return d.calorias; }
Creamos el histogram layout. Observe que el layout necesita conocer los ticks
del dominio de la escala de x para generar los intervalos del histograma.
//Escala en x
var xScale = d3.scale.linear()
.domain([0, d3.max(datos, value)])
.range([0, width]);
//Layout
var histLayout = d3.layout.histogram()
.bins(xScale.ticks(40))
.value(value);
Hemos definido la cantidad de 'bins', esto es, en la práctica, la cantidad de barras que tendrá nuestro histograma. En este caso, estamos dividiendo el dominio de nuestra escala en 40 intervalos disjuntos de misma longitud. Recuerde que, en el histograma, la altura de las barras representa la cantidad de valores que caen en cada uno de estos intervalos. Esto es distinto de un gráfico de barras en el que se grafica alguna observable asociada a un conjunto de entidades.
La variable histLayout
es una función de layout. Cuando la aplicamos a nuestros datos, se calcula, entre otras cosas, la posición en la que dibujaremos las barras y la cantidad de valores que caen dentro de cada intervalo. Después de ejecutar el siguiente código, observe la variable hist
en la consola.
var hist = histLayout(datos);
Finalmente, graficamos las barras:
// Escala en y
var yScale = d3.scale.linear()
.domain([0, d3.max(hist, function (d) { return d.y; })])
.range([0,height]);
//Creando svg
var svg = d3.select('#ejemplo-a01').selectAll('svg').data([hist]);
svg.enter().append('svg');
svg
.attr('width', width + marginLeft)
.attr('height', height + marginBottom);
//Definimos el eje x
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var gAxis = svg.selectAll('g.eje').data([hist]);
gAxis.enter().append("g")
.attr("class", "eje");
gAxis
.attr("transform", "translate(" + marginLeft + "," + (height + 1) + ")")
.call(xAxis);
gAxis.exit().remove();
// Creamos un grupo para cada barra
var gBars = svg.selectAll('g.bar').data(hist);
gBars.enter().append('g')
.classed('bar', true);
// Trasladamos los grupos
gBars.attr('transform', function(d) {
return 'translate(' + ( marginLeft + xScale(d.x) ) + ', ' + 0 + ')';
});
gBars.exit().remove();
// Creamos las barras
var rects = gBars.selectAll('rect.bar').data(function(d) { return [d]; });
rects.enter().append('rect')
.classed('bar', true)
.attr('fill', 'blue')
.attr('x', 1)
.attr('y', height)
.attr('width', xScale(hist[0].dx) - 1)
.attr('height', 0);
rects.transition().duration(2000)
.attr('y', function(d) { return height - yScale(d.y)}) //Observe el posicionamiento de la barra
.attr('height', function (d) { return yScale(d.y)})
.attr('width', xScale(hist[0].dx) - 1);
rects.exit().remove();