Pregunta

Necesito hacer una pirámide de población de aspecto clásico con D3.js.Algo parecido a esta imagen:enter image description here

He encontrado algunos ejemplos que se ven realmente bien (este y este) pero son más complejos de lo que estoy buscando.¿Alguien conoce un buen ejemplo SIMPLE que pueda ver?¿Algún consejo para empezar esto?¿Debería hacer dos gráficos de barras uno al lado del otro, uno para cada grupo de sexo?

¿Fue útil?

Solución

La clave para hacer una visualización como esta es dedicar una buena cantidad de tiempo a configurar el diseño de antemano antes de comenzar a dibujar algo.

Hay algunas medidas clave que querrás utilizar para hacer tu vida mucho más fácil cuando llegue el momento de crear las escalas y los ejes de tu gráfico.Entonces, puedes hacer uso de <g> elementos con traducciones para que en cada "sección" de su gráfico, pueda trabajar en coordenadas locales.

El objetivo es crear dos regiones reflejadas como esta:

two mirrored regions

Esto le permitirá compartir las mismas escalas para las dimensiones x e y entre las dos regiones.

Para definir estas regiones, primero puede configurar algunos valores para los márgenes del interior de su svg y luego crear un grupo para ubicarse dentro de esos márgenes.Esta es una práctica común en las visualizaciones d3 y, si aún no está familiarizado con ella, este es un buen momento para aprender.Por lo general, se parece a esto:

var width = 400,
    height = 300;

var margin = {
  top: 20,
  right: 10
  bottom: 40,
  left: 10
};

var svg = d3.select('body').append('svg')
  .attr('width', margin.left + width + margin.right)
  .attr('height', margin.top + height + margin.bottom)
  .append('g')
    .attr('class', 'inner-region')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

Esta es una buena práctica a seguir porque le permite dejar espacio en su documento svg para las marcas de los ejes, las etiquetas y los títulos, sin tener que tener en cuenta ese espacio al colocar partes de la visualización en sí.Luego, si descubre que necesita más espacio, puede simplemente ajustar un valor en la parte superior de su código, en lugar de reposicionar todo el diagrama.

Los otros puntos que son importantes son las coordenadas x de los dos ejes y.En otras palabras, los puntos en los que la población es cero para hombres y mujeres (que se muestran como líneas rojas a continuación).Estarán a una distancia establecida de la línea central de su región interior (que se muestra como una línea azul a continuación):

middle margin

Puede agregar una propiedad de margen medio al objeto de margen creado anteriormente para hacer referencia a este valor:

margin.middle = 28;

Querrá crear variables para almacenar las posiciones de las dos líneas rojas de arriba.Por ahora, llamémoslos pointA (la coordenada x de la línea cero para la población masculina) y pointB (el punto correspondiente a la población femenina).

var regionWidth = (width/2) - margin.middle;

var pointA = regionWidth,
    pointB = width - regionWidth;

Una vez que haya configurado estos puntos, las cosas se volverán mucho más simples, ya que puede simplemente conectar estos valores en una transformación svg para traducir los objetos que cree a esas posiciones.

La parte más complicada serán los dos ejes y centrales, que comparten un único conjunto de etiquetas.Para ello, necesitará tener un buen conocimiento de cómo d3.svg.axis() crea sus etiquetas de texto y qué propiedades se pueden manipular.Hay cuatro propiedades importantes que debes conocer para esto:

  1. axis.orient(direction) especifica la dirección en la que apuntan las marcas, saliendo del eje.Esto será un poco confuso en este caso porque queremos que las marcas apunten hacia el centro, por lo que el eje izquierdo tendrá .orient('right') y el eje derecho tendrá .orient('left')

  2. axis.tickSize(inner,outer) establece la longitud (en unidades svg) de las marcas que salen del eje.Las marcas "externas" son las que se encuentran en los puntos finales del eje y se pueden configurar para 0 en este caso porque estamos usando una escala ordinal con bandas de rango, por lo que los puntos finales no representan valores.Elija un valor pequeño para los ticks internos; para este ejemplo usaré 4.

  3. axis.tickPadding(padding) establece qué tan lejos del final de la marca de verificación se coloca el ancla de texto del texto de la etiqueta.Queremos colocar el ancla de texto en el centro de la imagen, justo entre los dos ejes.Como ya conocemos el margen medio (la distancia desde la línea central a cada eje) y conocemos el tickSize (la longitud de los ticks), podemos colocarlos en el centro tomando la diferencia de estos dos valores: .tickPadding(margin.middle - 4).

  4. axis.tickFormat(format) especifica el formato de las etiquetas de marca.Se puede configurar en la cadena vacía para eliminar las etiquetas de marca de uno de los ejes, de modo que no se produzca superposición: .tickFormat('')

Entonces, los dos ejes y se pueden definir así:

var yAxisLeft = d3.svg.axis()
  .scale(yScale)
  .orient('right')
  .tickSize(4,0)
  .tickPadding(margin.middle - 4);

var yAxisRight = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .tickSize(4,0)
  .tickFormat('');

Luego, cuando dibuje el eje y izquierdo, seleccione su <text> elementos y establecer el anclaje de texto para que sea middle entonces estarán centrados alrededor del ancla:

.call(yAxisLeft)
  .selectAll('text')
  .style('text-anchor', 'middle');

AQUÍ es un ejemplo simple de un gráfico completo que utiliza algunos datos artificiales.He intentado comentar la mayor cantidad posible de la estructura general para que sea fácil de seguir.También hice un translation(x,y) función para hacer que las coordenadas xey de cada traducción sean más fáciles de detectar que si se usara la concatenación de cadenas.Puede encontrar su definición al final del guión.

Espero que esto ayude, avíseme si tiene preguntas sobre los detalles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top