2012-06-28 32 views
7

Estoy usando D3.js y tengo problemas para configurar un diseño apilado para un gráfico de área con varias series. Tengo dos estructuras posibles de mis datos (si eso ayuda). Uno de ellos es los datos en bruto alimentados a la secuencia de comandos, en esta estructura:Área apilada en D3.js

var data = [{key: 'Group1', value: 37, date: '04/23/12'}, 
      {key: 'Group2', value: 12, date: '04/23/12'}, 
      {key: 'Group3', value: 46, date: '04/23/12'}, 
      {key: 'Group1', value: 32, date: '04/24/12'}, 
      {key: 'Group2', value: 19, date: '04/24/12'}, 
      {key: 'Group3', value: 42, date: '04/24/12'}, 
      {key: 'Group1', value: 45, date: '04/25/12'}, 
      {key: 'Group2', value: 16, date: '04/25/12'}, 
      {key: 'Group3', value: 44, date: '04/25/12'}, 
      {key: 'Group1', value: 24, date: '04/26/12'}, 
      {key: 'Group2', value: 52, date: '04/26/12'}, 
      {key: 'Group3', value: 64, date: '04/26/12'}] 

segunda es una estructura anidada, creado mediante este código:

pData = d3.nest() 
      .key(function(d) { return d.key; }) 
      .map(data); 

Resultando en esta estructura:

pData = {Group1: [{date: 04/23/12, key: "Group1", value: 37}, 
        {date: 04/24/12, key: "Group1", value: 32}, 
        {date: 04/25/12, key: "Group1", value: 45}, 
        ...], 
     Group2: [{date: 04/23/12, key: "Group2", value: 12}, 
        {etc, etc, etc}], 
     GroupX: [...] } 

Mis preguntas son: ¿Cómo configuro un generador d3.layout.stack(), usando una de las estructuras de datos anteriores (o alguna variación), para crear una cadena apilada UCTURA para mis datos tal que puedo pasarlo a un generador de área similar a esto:

var areaGenerator = d3.svg.area() 
    .interpolate('monotone') 
    .x(function(d) { return x(d.date); }) 
    .y0(h) 
    .y1(function(d) { return y(d.value); }); 

Respuesta

12

Debe alimentar a una serie de capas para el diseño de pila, por lo que lo primero que debe cambiar es utilizar nest.entries en lugar de nest.map . Esto devuelve una matriz de objetos con un campo key (como "Grupo1") y una matriz values que contiene los registros asociados. Luego, debe especificar un descriptor de acceso stack.values para que el diseño de la pila pueda acceder a la matriz values para cada capa.

También tendrá que definir adecuada x y y descriptores de acceso a la disposición de pila de modo que puedan entender los datos de entrada: el -accessor x deberían volver d.date y el -accessor y debería hacerlo devolver d.value. También deberá convertir las cadenas de fechas en Fechas; puede usar d3.time.format para ayudar con esto. Por ejemplo:

var format = d3.time.format("%m/%d/%y"); 
data.forEach(function(d) { d.date = format.parse(d.date); }); 

Por último, cambiar la definición del área para que el y0 línea de base se define como y(d.y0) y la línea superior Y1 se define como y(d.y0 + d.y).

Aquí está un ejemplo de trabajo:

+1

increíblemente útil. ¡Gracias por la respuesta! – mbeasley

+0

¡Muy útil, gracias! Merece la pena señalar noobs de Javascript (como yo!) Que el + antes del d.valor (en la devolución de datos) se convierte en un número - ver [aquí] (http://xkr.us/articles/javascript/unary -añadir/). En la devolución de llamada, ¿cómo se asignan los valores y0? Usé el código [this] (http://pastebin.com/amjkBRYV) para inspeccionar, y obtuve [este] (http://i.imgur.com/lQFyJNL.png) salida. Cada objeto se registra dos veces, antes y después de la edición. Antes, solo contiene datos de la csv; luego, tiene un "y0 = 0", como configuré, pero (cuando se profundiza en Chrome) también una y, y una y0 distinta de cero. ¿Que esta pasando ahí? – scubbo

+0

(Como referencia, estoy tratando de manipular el valor y0 para que el gráfico muestre totales acumulados, en lugar de valores en cada punto) Lo siento si recibe varias notificaciones de mis ediciones anteriores: no está acostumbrado al estilo StackOverflow, hizo algunas errores! – scubbo