2012-08-02 7 views
7

Ich versuche, die mittlere Lebensdauer unserer Kunden in D3.js graphisch darzustellen. Ich habe die Daten grafisch dargestellt, aber ich kann nicht herausfinden, wie man Referenzlinien zieht, die die mittlere Lebensdauer zeigen. Ich möchte vertikale und horizontale Referenzlinien, die meine Daten mit dem 50% -Wert der y-Achse schneiden.Referenzlinie für Liniendiagramm

Hier ist, was ich zur Zeit: median lifetime

Die vertikale Referenzlinie muss die Daten in der gleichen Stelle wie die horizontale Bezugslinie schneiden.

Hier ist mein Code:

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) + ')'); 
}); 

Antwort

4

Sie müssen den Punkt suchen, wo die Kunden 50% in Ihrer Linie sind (ca. 7 Wochen), das ist es, die Suche den Index i wo breakdown[i]/paying.length in der Nähe von 0,5, speichern B. indexMedianCustomers (Beispiel) und ändern Sie Ihren Code in

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]); 
     }) 
);