2012-08-02 23 views
7

Estoy tratando de graficar la vida media de nuestros clientes en D3.js. Tengo los datos graficados, pero no puedo imaginar cómo dibujar líneas de referencia que muestren la duración media. Quiero líneas de referencia verticales y horizontales que crucen mis datos en el 50% del valor del eje y.Línea de referencia para el gráfico de líneas

Aquí es lo que tengo actualmente: median lifetime

La línea vertical de referencia necesita para intersectar los datos en el mismo lugar que la línea horizontal de referencia.

Aquí está mi código:

d3.json('data.json', function(billingData) { 
    var paying = billingData.paying; 
    var w = 800; 
    var h = 600; 
    var secondsInInterval = 604800000; // Seconds in a week 

    var padding = 50; 

    var age = function(beginDate, secondsInInterval) { 
     // Calculate how old a subscription is given it's begin date 

     var diff = new Date() - new Date(beginDate); 
     return Math.floor(diff/secondsInInterval); 
    } 

    var maxAge = d3.max(paying, function(d) { return age(d.subscription.activated_at, secondsInInterval); }); 

    var breakdown = new Array(maxAge); 

    $.each(paying, function(i,d) { 
     d.age = age(d.subscription.activated_at, secondsInInterval); 
     for(var i = 0; i <= d.age; i++) { 
      if (typeof breakdown[i] == 'undefined') breakdown[i] = 0; 
      breakdown[i]++; 
     } 
    }); 

    // Scales 
    var xScale = d3.scale.linear().domain([0, maxAge]).range([padding,w-padding]); 
    var yScale = d3.scale.linear().domain([0, 1]).range([h-padding,padding]); 

    // Axes 
    var xAxis = d3.svg.axis().scale(xScale).tickSize(6,3).orient('bottom'); 
    var yAxis = d3.svg.axis().scale(yScale).tickSize(6,3).tickFormat(d3.format('%')).orient('left'); 

    var graph = d3.select('body').append('svg:svg') 
      .attr('width', 800) 
      .attr('height', 600); 

    var line = graph.selectAll('path.line') 
      .data([breakdown]) 
      .enter() 
      .append('svg:path') 
      .attr('fill', 'none') 
      .attr('stroke', 'blue') 
      .attr('stroke-width', '1') 
      .attr("d", d3.svg.line() 
      .x(function(d,i) { 
       return xScale(i); 
      }) 
      .y(function(d,i) { 
       return yScale(d/paying.length); 
      }) 
    ); 

    var xMedian = graph.selectAll('path.median.x') 
      .data([[[maxAge/2,0], [maxAge/2,1]]]) 
      .enter() 
      .append('svg:path') 
      .attr('class', 'median x') 
      .attr("d", d3.svg.line() 
      .x(function(d,i) { 
       return xScale(d[0]); 
      }) 
      .y(function(d,i) { 
       return yScale(d[1]); 
      }) 
    ); 

    var yMedian = graph.selectAll('path.median.y') 
      .data([[[0,.5], [maxAge,0.5]]]) 
      .enter() 
      .append('svg:path') 
      .attr('class', 'median y') 
      .attr("d", d3.svg.line() 
      .x(function(d,i) { 
       return xScale(d[0]); 
      }) 
      .y(function(d,i) { 
       return yScale(d[1]); 
      }) 
    ); 

    graph.append('g').attr('class', 'x-axis').call(xAxis).attr('transform', 'translate(0,' + (h - padding) + ')') 
    graph.append('g').attr('class', 'y-axis').call(yAxis).attr('transform', 'translate(' + padding + ',0)'); 
    graph.append('text').attr('class', 'y-label').attr('text-anchor', 'middle').text('customers').attr('transform', 'translate(10,' + (h/2) + '), rotate(-90)'); 
    graph.append('text').attr('class', 'x-label').attr('text-anchor', 'middle').text('lifetime (weeks)').attr('transform', 'translate(' + (w/2) + ',' + (h - padding + 40) + ')'); 
}); 

Respuesta

4

Es necesario buscar el punto donde están los clientes 50% en su línea (alrededor de 7 semanas), eso es todo, buscar el índice de i donde breakdown[i]/paying.length es cerca de 0,5, salvo ese índice como indexMedianCustomers (por ejemplo) y modificar su código en

var xMedian = graph.selectAll('path.median.x') 
     .data([[[indexMedianCustomers,0], [indexMedianCustomers,1]]]) 
     .enter() 
     .append('svg:path') 
     .attr('class', 'median x') 
     .attr("d", d3.svg.line() 
     .x(function(d,i) { 
      return xScale(d[0]); 
     }) 
     .y(function(d,i) { 
      return yScale(d[1]); 
     }) 
); 
Cuestiones relacionadas