如何使d3.js框图处理大数据集?

时间:2016-05-24 05:31:55

标签: css d3.js web

我在调用d3.js函数时使用box plot

  • 使用小型数据集工作正常。但它不适用于大型 数据集(900 000数据)。
  • 我尝试过很多数据集,但它只使用了一小部分数据集 数据及其对大量数据的影响。
  • 我尝试为框图调试d3.js脚本,但无法进行调试 找到数据集变为null的位置。

d3.js图表的性能会随着数据集的增加而降低吗?我该如何优化呢?

以下是代码:

 function box(g) {
    g.each(function(data, i) {
      //d = d.map(value).sort(d3.ascending);
      //var boxIndex = data[0];
      //var boxIndex = 1;
      var d = data[1].sort(d3.ascending);
      var t =  tableData.sort(function(a, b){return a-b;});
     // console.log(boxIndex); 
      //console.log(d); 

      var g = d3.select(this),
          n = t.length;
         min = 0,

         max = d[n-1];

      // Compute quartiles. Must return exactly 3 elements.
      var quartileData = [];
      quartileData[0]=d[1];
      quartileData[1]=parseFloat(d[2]);
      quartileData[2]=d[3];
      var data1 = parseFloat(d[1]);
      var data2 = parseFloat(d[3]);
      var common = data2-data1;
      var value = common.toFixed(5);
      // Compute whiskers. Must return exactly 2 elements, or null.
      var  whiskerData= [];
       whiskerData[0] = (data1 - ((value)*1.5)).toFixed(5);
       whiskerData[1]=  (data2 + ((value)*1.5)).toFixed(5);

       // Compute whiskers. Must return exactly 2 elements, or null.
       var whiskerIndices = [];
       var isRangeFound = false;
       whiskerIndices[0] = $.map( t , function( val,i ) 
        {
            if(whiskerData[0]< parseFloat(val) && !isRangeFound)
            {
                isRangeFound = true;
                return i;
            }
       });
       var isRangeFound1 = false;
       whiskerIndices[1] = $.map( t , function( val,i ) 
            {
                if(whiskerData[1] < parseFloat(val) && !isRangeFound1)
                {
                    isRangeFound1 = true;
                    return i-1;

                }
           });


      // Compute outliers. If no whiskers are specified, all data are "outliers".
      // We compute the outliers as indices, so that we can join across transitions!
      var outlierIndices = whiskerIndices
          ? d3.range(0, whiskerIndices[0]).concat(d3.range(parseInt(whiskerIndices[1]) + 1, n))
          : d3.range(n);

      // Compute the new x-scale.
      var x1 = d3.scale.linear()
              .domain(domain && domain.call(this,t, i) || [minBound, maxBound])
              .range([height, 0]);


      // Retrieve the old x-scale, if this is an update.
      var x0 = this.__chart__ || d3.scale.linear()
          .domain([0, Infinity])
         // .domain([0, max])
          .range(x1.range());

      // Stash the new scale.
      this.__chart__ = x1;

      // Note: the box, median, and box tick elements are fixed in number,
      // so we only have to handle enter and update. In contrast, the outliers
      // and other elements are variable, so we need to exit them! Variable
      // elements also fade in and out.

      // Update center line: the vertical line spanning the whiskers.
      var center = g.selectAll("line.center")
          .data(whiskerData ? [whiskerData] : []);

     //vertical line
      center.enter().insert("line", "rect")
          .attr("class", "center")
          .attr("x1", width / 2)
          .attr("y1", function(d) { return x0(d[0]); })
          .attr("x2", width / 2)
          .attr("y2", function(d) { return x0(d[1]); })
          .style("opacity", 1e-6)
        .transition()
          .duration(duration)
          .style("opacity", 1)
          .attr("y1", function(d) { return x1(d[0]); })
          .attr("y2", function(d) { return x1(d[1]); });

      center.transition()
          .duration(duration)
          .style("opacity", 1)
          .attr("y1", function(d) { return x1(d[0]); })
          .attr("y2", function(d) { return x1(d[1]); });

      center.exit().transition()
          .duration(duration)
          .style("opacity", 1e-6)
          .attr("y1", function(d) { return x1(d[0]); })
          .attr("y2", function(d) { return x1(d[1]); })
          .remove();

      // Update innerquartile box.
      var box = g.selectAll("rect.box")
          .data([quartileData]);

      box.enter().append("rect")
          .attr("class", "box")
          .attr("x", 0)
          .attr("y", function(d) { return x0(d[2]); })
          .attr("width", width)
          .attr("height", function(d) { return x0(d[0]) - x0(d[2]); })
        .transition()
          .duration(duration)
          .attr("y", function(d) { return x1(d[2]); })
          .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });

      box.transition()
          .duration(duration)
          .attr("y", function(d) { return x1(d[2]); })
          .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });

      // Update median line.
      var medianLine = g.selectAll("line.median")
          .data((quartileData[1]));

      medianLine.enter().append("line")
          .attr("class", "median")
          .attr("x1", 0)
          .attr("y1", x0)
          .attr("x2", width)
          .attr("y2", x0)
        .transition()
          .duration(duration)
          .attr("y1", x1)
          .attr("y2", x1);

      medianLine.transition()
          .duration(duration)
          .attr("y1", x1)
          .attr("y2", x1);

      // Update whiskers.
      var whisker = g.selectAll("line.whisker")
          .data(whiskerData || []);

      whisker.enter().insert("line", "circle, text")
          .attr("class", "whisker")
          .attr("x1", 0)
          .attr("y1", x0)
          .attr("x2", 0 + width)
          .attr("y2", x0)
          .style("opacity", 1e-6)
        .transition()
          .duration(duration)
          .attr("y1", x1)
          .attr("y2", x1)
          .style("opacity", 1);

      whisker.transition()
          .duration(duration)
          .attr("y1", x1)
          .attr("y2", x1)
          .style("opacity", 1);

      whisker.exit().transition()
          .duration(duration)
          .attr("y1", x1)
          .attr("y2", x1)
          .style("opacity", 1e-6)
          .remove();

      var outlier = g.selectAll("circle.outlier")
      .data(outlierIndices, Number);

  outlier.enter().insert("circle", "text")
      .attr("class", "outlier")
      .attr("r", 5)
      .attr("cx", width / 2)
      .attr("cy", function(i) { return x0(t[i]); })
      .style("opacity", 1e-6)
    .transition()
      .duration(duration)
      .attr("cy", function(i) { return x1(t[i]); })
      .style("opacity", 1);

  outlier.transition()
      .duration(duration)
      .attr("cy", function(i) { return x1(t[i]); })
      .style("opacity", 1);

  outlier.exit().transition()
      .duration(duration)
      .attr("cy", function(i) { return x1(t[i]); })
      .style("opacity", 1e-6)
      .remove();

      // Compute the tick format.
      var format = tickFormat || x1.tickFormat(8);


      // Update box ticks.
      var boxTick = g.selectAll("text.box")
          .data(quartileData);
     if(showLabels == true) {
      boxTick.enter().append("text")
          .attr("class", "box")
          .attr("dy", ".3em")
          .attr("dx", function(d, i) { return i & 1 ? 6 : -6 ;})
          .attr("x", function(d, i) { return i & 1 ?  + width : 0; })
          .attr("y", x0)
          .attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; })
          .text(format)
        .transition()
          .duration(duration)
          .attr("y", x1);
    }

      boxTick.transition()
          .duration(duration)
          .text(format)
          .attr("y", x1);

      // Update whisker ticks. These are handled separately from the box
      // ticks because they may or may not exist, and we want don't want
      // to join box ticks pre-transition with whisker ticks post-.
      var whiskerTick = g.selectAll("text.whisker")
          .data(whiskerData || []);
    if(showLabels == true) {
      whiskerTick.enter().append("text")
          .attr("class", "whisker")
          .attr("dy", ".3em")
          .attr("dx", 6)
          .attr("x", width)
          .attr("y", x0)
          .text(format)
          .style("opacity", 1e-6)
        .transition()
          .duration(duration)
          .attr("y", x1)
          .style("opacity", 1);
    }
      whiskerTick.transition()
          .duration(duration)
          .text(format)
          .attr("y", x1)
          .style("opacity", 1);

      whiskerTick.exit().transition()
          .duration(duration)
          .attr("y", x1)
          .style("opacity", 1e-6)
          .remove();
    });
    d3.timer.flush();
  }

function getBoxPlotChart(csvFetch,chartDiv,outilerTotalValue,tableDataValue)
{

    var labels = true; 

    $("#" + chartDiv).empty();

    var margin = {top: 30, right: 50, bottom: 70, left: 50};
    var  width = 410 - margin.left - margin.right;
    var height = 380 - margin.top - margin.bottom;

    var min = Infinity,
        max = -Infinity;
    tableData =  tableDataValue;
        var data = [];
        data[0] = [];


        // add more rows if your csv file has more columns

        // add here the header of the csv file
        data[0][0] = "";


        // add more rows if your csv file has more columns

        data[0][1] = [];

            var v1 = parseFloat(csvFetch.firstQuartile),
            v2 = parseFloat(csvFetch.medianValue),
            v3=parseFloat(csvFetch.thirdQuartile),
            v4=parseFloat(csvFetch.minValue),
            v5=parseFloat(csvFetch.maxValue);


            outlierData = outilerTotalValue;
            var rowMax =  Math.max(v1, Math.max(v2, Math.max(v3,v5)));
            //var rowMin = Math.min(v4, Math.max(v2, Math.max(v3,v1)));
            var rowMin=0;
                // add more variables if your csv file has more columns

            var data1 = parseFloat(v1);
              var data2 = parseFloat(v3);
              var absDiff = Math.abs(data1-data2);
              var iqrValue = absDiff * 1.5;
              //var common = data2-data1;
              //var value = common.toFixed(5);

              // Compute whiskers. Must return exactly 2 elements, or null.
              var  fence= [];
              fence[0] = data1 - iqrValue;
              fence[1]=  data2 + iqrValue;
              var lowerFence=fence[0];
              var upperFence=fence[1];
           /*End : To correct Y axis labelling : Pranjal    */
            var rowMax1 =  Math.max(v1, Math.max(v2, Math.max(v3,v5)));
            var rowMin1 = Math.min(v4, Math.max(v2, Math.max(v3,v1)));

            minBound=Math.floor(Math.min(lowerFence,rowMin1));
            maxBound=Math.ceil(Math.max(upperFence,rowMax1));



            data[0][1].push(v1);
            data[0][1].push(v2);
            data[0][1].push(v3);
            data[0][1].push(v4);
            data[0][1].push(v5);



            // add more rows if your csv file has more columns

            if (rowMax > max) max = rowMax;
            if (rowMin < min) min = rowMin; 


        var chart = d3.box()
            //.whiskers(iqr(1.5))
            .height(height) 
            .domain([minBound, maxBound])
            .showLabels(labels);


        var svg = d3.select("#" + chartDiv).append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .attr("class", "box")    
            .append("g")
            .attr("transform", "translate(" + (margin.left+200) + "," + margin.top + ")");

        // the x-axis
            var x = d3.scale.ordinal()     
            .domain( data.map(function(d) { console.log(d); return d[0]; } ) )      
            .rangeRoundBands([0 , width], 0.7, 0.3);        

        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

        // the y-axis
        var y = d3.scale.linear()
            .domain([minBound, maxBound])
            .range([height + margin.top, 0 + margin.top]);

        var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

        // draw the boxplots    
        svg.selectAll(".box")      
          .data(data)
          .enter().append("g")
            .attr("transform", function(d) { return "translate(" +  x(d[0])  + "," + margin.top + ")"; } )
          .call(chart.width(x.rangeBand())); 


        /*// add a title
        svg.append("text")
            .attr("x", (width / 2))             
            .attr("y", 0 + (margin.top / 2))
            .attr("text-anchor", "middle")  
            .style("font-size", "18px");*/
            /* Start: Bug: attribute label should present : Salman : 11/03/2016 */
            //    .text(csvFetch.attributeName+" "+"Vs"+" "+"Distribution");
            /* End: Bug: attribute label should present : Salman : 11/03/2016 */

         // draw y axis labelling
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text") // and text1
             .attr("transform", "rotate(0)")
             .attr("y", 6)
             .attr("dy", ".71em")
             /* Start: Bug: y axis label was getting hidden : Salman : 11/03/2016 */ 
             .style("text-anchor", "start")
             /* End: Bug: y axis label was getting hidden : Salman : 11/03/2016 */
             .text(csvFetch.attributeName);     

        // draw x axis labelling
        svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + (height  + margin.top + 10) + ")")
          .call(xAxis)
          .append("text")             // text label for the x axis
          .attr("x", (width / 2)+350 )
          .attr("y",  10 )
          .attr("dy", ".71em");




    // Returns a function to compute the interquartile range.
    /*function iqr(k) {
      return function(d, i) {
        var q1 =d[1];
        var q3 = d[3];
        var  iqr = (q3 - q1)*k;
      };
    }*/


}

0 个答案:

没有答案