代码之家  ›  专栏  ›  技术社区  ›  Datacrawler

d3图表值未分组(来自json加载)

  •  1
  • Datacrawler  · 技术社区  · 6 年前

    我有一个JSON查询,我用一个D3图表来表示数据。似乎这个组织(国家)不起作用。我们可以为每个国家(如加拿大)提供多条线路。部分代码:

    data.forEach(function (a) {
        groups[a.value] = groups[a.value] || [];
        groups[a.value].push(a);    
    });
    
    result = Object.keys(groups).reduce(function (r, k) {
        return r.concat(groups[k]);
    }, []);
    

    理想情况下,我希望通过更改脚本来实现这一点。第二个解决方案是更改JSON的格式(操作)。我正努力集中在第一个解决方案上…代码段如下:

          var json_data= {"headers":["Dimension 1","Metric 1","Metric 2"],"rows":[["Australia",174,23],["Canada",502,17],["France",242,37],["Germany",102,42],["United Kingdom",126,44],["United States",1246,47],["Australia",680,80],["Canada",1241,66],["Canada",1241,66],["France",150,30],["Germany",244,22],["United Kingdom",501,9],["United States",4960,41],["Australia",9,8],["Canada",3655,70],["France",1654,95],["Germany",1190,36],["United Kingdom",1222,38],["United States",7941,53],["Australia",6829,56],["Canada",1664,75],["France",2995,88],["Germany",1487,100],["United Kingdom",9245,29],["United States",9008,66],["Australia",9376,7],["Canada",1531,31],["France",5421,22],["Germany",6975,41],["United Kingdom",4320,100],["United States",3200,41],["Australia",6688,41],["Canada",699,42],["France",5403,70],["Germany",6377,49],["United Kingdom",2471,14],["United States",6650,4],["Australia",865,70],["Canada",511,20],["France",981,36],["Germany",57,10],["United Kingdom",675,38],["United States",40,72],["Australia",400,63],["Canada",971,90],["France",357,93],["Germany",820,40],["United Kingdom",520,32],["United States",448,24],["Australia",513,40],["Canada",977,8],["France",118,84],["Germany",161,29],["United Kingdom",239,89],["United States",327,79]]};
          var headers = json_data.headers;
          var platform_data = json_data.rows;
          var data = [];
          var metric = 0;
          for (var i in platform_data)
            {
              var dimension = platform_data[i][0];
              metric = (platform_data[i][1]).toFixed(0);
              object = { label: dimension, value: metric};
              data.push(object);
            }
    
    //Sorting
    var data = data,
        groups = Object.create(null),
        result = [];
    
    data.forEach(function (a) {
        groups[a.value] = groups[a.value] || [];
        groups[a.value].push(a);    
    });
    
    result = Object.keys(groups).reduce(function (r, k) {
        return r.concat(groups[k]);
    }, []);
    
    
    //Descending - Reverse JSON order
    var objAssetSelection = result.reverse();
    data = objAssetSelection;
    
    //D3 Code
    
            var div = d3.select("body").append("div").attr("class", "toolTip");
        
            var axisMargin = 20,
                    margin = 40,
                    valueMargin = 4,
                    width = parseInt(d3.select('body').style('width'), 10),
                    height = parseInt(d3.select('body').style('height'), 10),
                    barHeight = (height-axisMargin-margin*2)* 0.4/data.length,
                    barPadding = (height-axisMargin-margin*2)*0.6/data.length,
                    data, bar, svg, scale, xAxis, labelWidth = 0;
        
            max = d3.max(data, function(d) { return d.value; });
        
            svg = d3.select('body')
                    .append("svg")
                    .attr("width", width)
                    .attr("height", height);
        
        
            bar = svg.selectAll("g")
                    .data(data)
                    .enter()
                    .append("g");
        
            bar.attr("class", "bar")
                    .attr("cx",0)
                    .attr("transform", function(d, i) {
                        return "translate(" + margin + "," + (i * (barHeight + barPadding) + barPadding) + ")";
                    });
        
            bar.append("text")
                    .attr("class", "label")
                    .attr("y", barHeight / 2)
                    .attr("dy", ".35em") //vertical align middle
                    .text(function(d){
                        return d.label;
                    }).each(function() {
                labelWidth = Math.ceil(Math.max(labelWidth, this.getBBox().width));
            });
        
            scale = d3.scale.linear()
                    .domain([0, max])
                    .range([0, width - margin*2 - labelWidth]);
        
            xAxis = d3.svg.axis()
                    .scale(scale)
                    .tickSize(-height + 2*margin + axisMargin)
                    .orient("bottom");
        
            bar.append("rect")
                    .attr("transform", "translate("+labelWidth+", 0)")
                    .attr("height", barHeight)
                    .attr("width", function(d){
                        return scale(d.value);
                    });
        
            bar.append("text")
                    .attr("class", "value")
                    .attr("y", barHeight / 2)
                    .attr("dx", -valueMargin + labelWidth) //margin right
                    .attr("dy", ".35em") //vertical align middle
                    .attr("text-anchor", "end")
                    .text(function(d){
                        return (d.value);
                    })
                    .attr("x", function(d){
                        var width = this.getBBox().width;
                        return Math.max(width + valueMargin, scale(d.value));
                    });
        
            bar
                    .on("mousemove", function(d){
                        div.style("left", d3.event.pageX+10+"px");
                        div.style("top", d3.event.pageY-25+"px");
                        div.style("display", "inline-block");
                        div.html((d.label)+"<br>"+(d.value));
                    });
            bar
                    .on("mouseout", function(d){
                        div.style("display", "none");
                    });
        
            svg.insert("g",":first-child")
                    .attr("class", "axisHorizontal")
                    .attr("transform", "translate(" + (margin + labelWidth) + ","+ (height - axisMargin - margin)+")")
                    .call(xAxis);
    @import url('https://fonts.googleapis.com/css?family=Roboto');
    
    body {
            font-family: "Roboto"!important;
            width: 100%;
            height: 500px;
            position: relative;
        }
    
        svg {
            width: 100%;
            height: 100%;
            position: center;
        }
    
        .toolTip {
            position: absolute;
            display: none;
            width: auto;
            height: auto;
            background: none repeat scroll 0 0 white;
            border: 0 none;
            border-radius: 8px 8px 8px 8px;
            box-shadow: -3px 3px 15px #888888;
            color: black;
            font: 12px sans-serif;
            padding: 5px;
            text-align: center;
        }
    
        text {
            font: 10px sans-serif;
            color: white;
        }
        text.value {
            font-size: 100%;
            fill: white;
        }
    
        .axisHorizontal path{
            fill: none;
        }
    
        .axisHorizontal .tick line {
            stroke-width: 1;
            stroke: rgba(0, 0, 0, 0.2);
        }
    
        .bar {
            fill: steelblue;
            fill-opacity: .9;
        }
    <script src="https://d3js.org/d3.v3.min.js"></script>
    1 回复  |  直到 6 年前
        1
  •  1
  •   Shashank    6 年前

    分组代码不正确。如果您控制台日志 data 分组数据之后,它是相同的未分组数据。

    为了更好地分组,您可以查看 d3.nest 。这是分组代码使用 d3.nest (分组数据基于 标签 并使用 d3.sum ( d3.sum ):

    var nested_data = d3.nest()
                        .key(function(d) { return d.label; })
                        .rollup(function (d) { 
                          return d3.sum(d, function(v) { return +v.value;})
                        }).entries(data);
    

    为了不干扰您的其余代码,我将通过以下方式将此嵌套的\数据映射到原始格式:

    data = nested_data.map(function(row) {
      return {label: row.key, value: row.values};
    });
    

    编辑:添加排序代码

    data.sort(function(a, b) { return a.value > b.value ? -1 : a.value === b.value ? 0 : 1; });
    

    使用上面的嵌套/分组,这里有一个代码段:

    var json_data= {"headers":["Dimension 1","Metric 1","Metric 2"],"rows":[["Australia",174,23],["Canada",502,17],["France",242,37],["Germany",102,42],["United Kingdom",126,44],["United States",1246,47],["Australia",680,80],["Canada",1241,66],["Canada",1241,66],["France",150,30],["Germany",244,22],["United Kingdom",501,9],["United States",4960,41],["Australia",9,8],["Canada",3655,70],["France",1654,95],["Germany",1190,36],["United Kingdom",1222,38],["United States",7941,53],["Australia",6829,56],["Canada",1664,75],["France",2995,88],["Germany",1487,100],["United Kingdom",9245,29],["United States",9008,66],["Australia",9376,7],["Canada",1531,31],["France",5421,22],["Germany",6975,41],["United Kingdom",4320,100],["United States",3200,41],["Australia",6688,41],["Canada",699,42],["France",5403,70],["Germany",6377,49],["United Kingdom",2471,14],["United States",6650,4],["Australia",865,70],["Canada",511,20],["France",981,36],["Germany",57,10],["United Kingdom",675,38],["United States",40,72],["Australia",400,63],["Canada",971,90],["France",357,93],["Germany",820,40],["United Kingdom",520,32],["United States",448,24],["Australia",513,40],["Canada",977,8],["France",118,84],["Germany",161,29],["United Kingdom",239,89],["United States",327,79]]};
          var headers = json_data.headers;
          var platform_data = json_data.rows;
          var data = [];
          var metric = 0;
          for (var i in platform_data)
            {
              var dimension = platform_data[i][0];
              metric = (platform_data[i][1]).toFixed(0);
              object = { label: dimension, value: metric};
              data.push(object);
            }
    
    //Sorting
    var data = data,
        groups = Object.create(null),
        result = [];
    
    /* data.forEach(function (a) {
        groups[a.value] = groups[a.value] || [];
        groups[a.value].push(a);    
    });
    
    result = Object.keys(groups).reduce(function (r, k) {
        return r.concat(groups[k]);
    }, []); */
    
    
    var nested_data = d3.nest()
    		    .key(function(d) { return d.label; })
                        .rollup(function (d) { 
                          return d3.sum(d, function(v) { return +v.value;})
                        }).entries(data);
                          
    data = nested_data.map(function(row) {
    	return {label: row.key, value: row.values};
    }).sort(function(a, b) { return a.value > b.value ? -1 : a.value === b.value ? 0 : 1; });
    //Descending - Reverse JSON order
    /* var objAssetSelection = result.reverse();
    data = objAssetSelection;
     */
    //D3 Code
    
            var div = d3.select("body").append("div").attr("class", "toolTip");
        
            var axisMargin = 20,
                    margin = 40,
                    valueMargin = 4,
                    width = parseInt(d3.select('body').style('width'), 10),
                    height = parseInt(d3.select('body').style('height'), 10),
                    barHeight = (height-axisMargin-margin*2)* 0.4/data.length,
                    barPadding = (height-axisMargin-margin*2)*0.6/data.length,
                    data, bar, svg, scale, xAxis, labelWidth = 0;
        
            max = d3.max(data, function(d) { return d.value; });
        
            svg = d3.select('body')
                    .append("svg")
                    .attr("width", width)
                    .attr("height", height);
        
        
            bar = svg.selectAll("g")
                    .data(data)
                    .enter()
                    .append("g");
        
            bar.attr("class", "bar")
                    .attr("cx",0)
                    .attr("transform", function(d, i) {
                        return "translate(" + margin + "," + (i * (barHeight + barPadding) + barPadding) + ")";
                    });
        
            bar.append("text")
                    .attr("class", "label")
                    .attr("y", barHeight / 2)
                    .attr("dy", ".35em") //vertical align middle
                    .text(function(d){
                        return d.label;
                    }).each(function() {
                labelWidth = Math.ceil(Math.max(labelWidth, this.getBBox().width));
            });
        
            scale = d3.scale.linear()
                    .domain([0, max])
                    .range([0, width - margin*2 - labelWidth]);
        
            xAxis = d3.svg.axis()
                    .scale(scale)
                    .tickSize(-height + 2*margin + axisMargin)
                    .orient("bottom");
        
            bar.append("rect")
                    .attr("transform", "translate("+labelWidth+", 0)")
                    .attr("height", barHeight)
                    .attr("width", function(d){
                        return scale(d.value);
                    });
        
            bar.append("text")
                    .attr("class", "value")
                    .attr("y", barHeight / 2)
                    .attr("dx", -valueMargin + labelWidth) //margin right
                    .attr("dy", ".35em") //vertical align middle
                    .attr("text-anchor", "end")
                    .text(function(d){
                        return (d.value);
                    })
                    .attr("x", function(d){
                        var width = this.getBBox().width;
                        return Math.max(width + valueMargin, scale(d.value));
                    });
        
            bar
                    .on("mousemove", function(d){
                        div.style("left", d3.event.pageX+10+"px");
                        div.style("top", d3.event.pageY-25+"px");
                        div.style("display", "inline-block");
                        div.html((d.label)+"<br>"+(d.value));
                    });
            bar
                    .on("mouseout", function(d){
                        div.style("display", "none");
                    });
        
            svg.insert("g",":first-child")
                    .attr("class", "axisHorizontal")
                    .attr("transform", "translate(" + (margin + labelWidth) + ","+ (height - axisMargin - margin)+")")
                    .call(xAxis);
    body {
            font-family: "Roboto"!important;
            width: 100%;
            height: 500px;
            position: relative;
        }
    
        svg {
            width: 100%;
            height: 100%;
            position: center;
        }
    
        .toolTip {
            position: absolute;
            display: none;
            width: auto;
            height: auto;
            background: none repeat scroll 0 0 white;
            border: 0 none;
            border-radius: 8px 8px 8px 8px;
            box-shadow: -3px 3px 15px #888888;
            color: black;
            font: 12px sans-serif;
            padding: 5px;
            text-align: center;
        }
    
        text {
            font: 10px sans-serif;
            color: white;
        }
        text.value {
            font-size: 100%;
            fill: white;
        }
    
        .axisHorizontal path{
            fill: none;
        }
    
        .axisHorizontal .tick line {
            stroke-width: 1;
            stroke: rgba(0, 0, 0, 0.2);
        }
    
        .bar {
            fill: steelblue;
            fill-opacity: .9;
        }
    <script src="https://d3js.org/d3.v3.min.js"></script>

    要了解有关d3-nest的更多信息,下面是一个很好的示例列表: http://bl.ocks.org/phoebebright/raw/3176159/

    希望这有帮助。