13 – Haciendo un gráfico de barras

Enlace al tutorial original: http://alignedleft.com/tutorials/d3/making-a-bar-chart

Haciendo un gráfico de barras

Última actualización: 30 de diciembre de 2012

Ahora vamos a integrar todo lo que hemos aprendido hasta ahora para generar un sencillo gráfico de barras con D3.

Empezaremos revisando el gráfico de barras que hicimos en su lugar utilizando elementos div. Luego adaptaremos este código para dibujar las barras con SVG, lo que nos dará más flexibilidad en la presentación visual. Por último, añadiremos etiquetas, para ver los valores con más claridad.

La antigua gráfica

Aquí tenemos lo que teníamos la última vez, con nuevos datos.

var dataset = ;d3.select("body").selectAll("div") .data(dataset) .enter() .append("div") .attr("class", "bar") .style("height", function(d) { var barHeight = d * 5; return barHeight + "px"; });

Gráfico de barras con divs

Puede ser difícil de imaginar, pero podemos mejorar claramente este simpe gráfico de barras hecho con divs.

El nuevo gráfico

Primero, necesitamos establecer el tamaño del nuevo SVG:

// Largeur et hauteurvar w = 500;var h = 100;

(Por supuesto, podrías llamar a w y h de otra manera, como svgWidth y svgHeight. Utilice lo que considere más claro. JavaScript tiene una cultura de eficiencia, por lo que a menudo verás variables de un solo carácter, código escrito sin espacios y otra sintaxis difícil de leer, pero eficiente desde el punto de vista de la programación.)

Entonces le decimos a D3 que cree un elemento SVG vacío y lo añada al DOM:

// Crée l'élément SVGvar svg = d3.select("body") .append("svg") .attr("width", w) .attr("height", h);

Esto inserta un nuevo elemento <svg> justo antes de la etiqueta de cierre </body>, y asigna al SVG las dimensiones de 500 por 100 píxeles. Esta declaración también pone el resultado en una nueva variable llamada svg, por lo que podemos fácilmente hacer referencia a SVG sin tener que volver a seleccionar más tarde usando algo como d3.select(«svg»).

Entonces, en lugar de crear divs, generamos rects y los añadimos al svg.

svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x", 0) .attr("y", 0) .attr("width", 20) .attr("height", 100);

Este código selecciona todos los rects dentro del svg. Por supuesto, aún no hay ninguno, por lo que se devuelve una selección vacía. (Raro, lo reconozco, pero quédate conmigo. Con D3, siempre tienes que seleccionar cualquier cosa con la que quieras trabajar, incluso si esa selección está vacía.)

A continuación, data(dataset) ve que tiene 20 valores en el conjunto de datos, por lo que llama a enter() 20 veces. enter(), a su vez, devuelve una selección de marcadores de posición para cada elemento de datos que no tiene un rect correspondiente – lo que significa todos los rects.

Para cada uno de los 20 marcadores de posición, append(«rect») inserta un rect en el DOM. Como aprendimos en la introducción a SVG, cada rect debe tener definidos los valores de x, y, ancho y alto. Usamos attr() para añadir estos atributos en cada uno de los rectos recién creados.

Es bonito, ¿verdad?

Una barra solitaria

De acuerdo, no estoy seguro. Todas las barras están presentes (mire el DOM de la página de demostración con su inspector web), pero todas ellas comparten los mismos valores de x, y, anchura y altura, con el resultado de que todas se superponen. Esto sigue sin ser visualización de datos.

Arreglemos primero el hecho de que se solapen. En lugar de utilizar una x de cero, le asignaremos un valor dinámico que corresponde a i, la posición de cada elemento en el conjunto de datos. Así que la primera barra será cero, pero las siguientes serán 21, luego 42, y así sucesivamente.

.attr("x", function(d, i) { return i * 21; // Largeur de barre de 20 plus 1 pour la marge})

Veinte barras

Aquí está el código en acción.

Funciona, pero no es súper flexible. Si tuviéramos más datos, las barras se sucederían a la derecha, ¡incluso después de que el SVG termine! Como cada barra tiene 20 píxeles de ancho, más 1 píxel de margen, un SVG de 500 píxeles de ancho sólo podría mostrar 23 elementos de datos. Fíjate en cómo se corta la barra 24:

Veinticuatro barras

Una buena práctica es utilizar coordenadas flexibles y dinámicas -alturas, anchuras, valores x y valores y- para que tu visualización se redimensione adecuadamente en función de tus datos.

Como con cualquier problema de programación, hay mil maneras de conseguirlo. Utilizaré uno sencillo. En primer lugar, cambiaré la línea donde establecemos la posición x de cada barra:

.attr("x", function(d, i) { return i * (w / dataset.length);})

Nota cómo el valor de x está ahora ligado directamente al ancho del SVG (w) y al número de valores de nuestro conjunto de datos (dataset.length). Esto es emocionante, porque ahora nuestras barras estarán espaciadas uniformemente, tanto si tenemos veinte barras:

Veinte barras espaciadas uniformemente

o sólo cinco:

Cinco barras espaciadas uniformemente

Este es el código hasta ahora.

Ahora deberíamos hacer que los anchos de las barras sean también proporcionales, de forma que se hagan más finas a medida que se añaden más datos, o más anchas cuando hay menos valores. Voy a añadir una nueva variable al lado de donde establecemos la altura y el ancho del SVG

// Largeur et hauteurvar w = 500;var h = 100;var barPadding = 1; // <-- Nouveau !

Entonces haz referencia a esta variable en la línea donde establecemos el ancho de cada barra. En lugar de un valor estático de 20, el ancho se definirá ahora como una fracción entre el ancho del SVG y el recuento de datos, menos el valor del margen:

.attr("width", w / dataset.length - barPadding)

Veinte barras espaciadas con anchos dinámicos

¡Funciona! Los anchos y las posiciones x de las barras se escalan correctamente tanto si hay veinte puntos, como si sólo hay cinco

Cinco barras espaciadas con anchos dinámicos

o incluso cien :

Cientos de barras espaciadas con anchos dinámicos

Para terminar, programemos la altura de cada barra. Uno espera que esto sea tan fácil como referenciar el valor d al establecer la altura:

.attr("height", function(d) { return d;});

Alturas dinámicas

Hum, eso suena raro. ¿Quizás podríamos hacer nuestros números un poco más grandes?

.attr("height", function(d) { return d * 4; // <-- Fois quatre !});

Alturas dinámicas

Desgraciadamente, no es tan fácil -queremos que nuestras barras crezcan desde el borde inferior, no desde el superior- pero no culpes a D3, culpa a SVG.

Recuerda de la introducción a SVG: al dibujar rectas, los valores x e y especifican las coordenadas de la esquina superior izquierda. Esto significa que el origen o punto de referencia de cada recto es su punto superior izquierdo. Para nuestros propósitos, sería teeeeeeellly más fácil si nuestro punto de referencia fuera el punto inferior izquierdo, pero eso simplemente no es cómo SVG funciona, y, francamente, SVG es bastante indiferente a sus sentimientos en la materia.

Dado que nuestras barras son para «crecer desde la parte superior», ¿dónde está «la parte superior» de cada barra en relación con la parte superior de SVG? Pues bien, la parte superior de cada barra se puede definir como una relación entre la altura del SVG y el valor de los datos correspondientes, así:

.attr("y", function(d) { return h - d; // Hauteur moins la valeur de la donnée})

Entonces, para poner el «fondo» de cada barra en la parte inferior del SVG, cada altura de los rects tiene que ser justo el valor de los datos en sí:

.attr("height", function(d) { return d; // Juste la valeur de la donnée});

Escalando desde abajo

Vamos a escalar un poco cambiando d por d * 4. (Nota: Más adelante aprenderemos más sobre las escalas D3, que ofrecen mejores formas de lograr esto.)

Creciendo desde abajo

Aquí está el código de nuestro gráfico donde nuestras barras crecen desde abajo.

Colores

Añadir un color es fácil. Sólo tienes que usar attr() para establecer un relleno:

.attr("fill", "teal");

El azul corresponde al color llamado teal

Barras azules

Aquí tienes un gráfico de barras completamente azul. Pero a menudo querrá ajustar el color de la forma para reflejar una de las cualidades de los datos. Eso significa que querrás programar los datos en color. (Para nuestro gráfico, esto resulta en una programación dual, en la que el mismo valor de datos se programa en dos propiedades visuales: altura y color.)

Usar datos para definir un color es como escribir una función que también hace referencia a d. Aquí sustituimos «teal» por una función personalizada:

.attr("fill", function(d) { return "rgb(0, 0, " + (d * 10) + ")";});

Barras azules con datos

Aquí está el código. No es una codificación visual especialmente útil, pero al menos tienes una idea de cómo traducir los datos en colores. Aquí, d se multiplica por 10, y luego se utiliza en el valor del azul en una definición de color rgb(). Cuanto mayor sea el valor de d (barras más grandes), más azul será la barra. Para valores más pequeños de d (barras más pequeñas) las barras serán menos azules (más cercanas al negro).

Etiquetas (o rótulos)

Los visuales son geniales, pero a veces necesitarás mostrar los valores de los datos en texto en tu visualización. Ahí es donde entran las etiquetas de valor, y son muy, muy fáciles de generar con D3.

Recuerdas de la introducción a SVG: puedes añadir elementos de texto al elemento SVG. Empezaremos por:

svg.selectAll("text") .data(dataset) .enter() .append("text")

¿Te suena? Al igual que hicimos con los rects, estamos haciendo lo mismo con los textos. Primero, selecciona lo que quieres, trae los datos, añade los nuevos elementos con enter() (que son sólo marcadores de posición en este punto), y finalmente añade los nuevos elementos de texto al DOM.

Completemos este código para incluir el valor de los datos en cada elemento de texto utilizando el text()

.text(function(d) { return d; })

y establezcamos los valores x e y para posicionar el texto. Es más fácil si simplemente copio/pego el mismo código que usamos arriba para las barras:

.attr("x", function(d, i) { return i * (w / dataset.length); }) .attr("y", function(d) { return h - (d * 4); });

¡Etiquetas!

¡Ajá! Etiquetas Pero algunas están cortadas por arriba. Probemos a moverlas hacia abajo, dentro de las barras, añadiendo unos píxeles a x e y:

.attr("x", function(d, i) { return i * (w / dataset.length) + 5; // +5 }) .attr("y", function(d) { return h - (d * 4) + 15; // +15 });

Etiquetas en barras

Mejor, pero no se lee. Afortunadamente, podemos solucionarlo:

.attr("font-family", "sans-serif") .attr("font-size", "11px") .attr("fill", "white");

¡Las etiquetas son realmente bonitas

Fantástico código! Si no eres un fanático de la tipografía, entonces es suficiente. Si, por el contrario, eres como yo, notarás que las etiquetas no están perfectamente alineadas en su barra. Es bastante fácil de arreglar. Utilicemos el atributo SVG text-anchor para centrar el texto horizontalmente con respecto a x:

.attr("text-anchor", "middle")

A continuación, vamos a cambiar la forma de calcular la posición x definiéndola como el lado izquierdo de cada barra más la mitad del ancho de la misma:

.attr("x", function(d, i) { return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2; })

También vamos a editar las etiquetas un píxel para que el espaciado sea perfecto:

.attr("y", function(d) { return h - (d * 4) + 14; // 15 vaut est maintenant 14 })

Etiquetas centradas

¡Listo! Ahora dejemos de lado los gráficos de barras por un momento.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *