简体   繁体   中英

D3: How to show only top 3 of 6 items in bar chart?

I'm an extreme newbie to D3. I am working with a web map built in LeafletJS and have put a D3 bar chart into a popup that shows the various ethnic groups for a district in Afghanistan. In my real project, I have over 26 ethnic groups in the area and I only want to show the top 3 largest ethnic groups in the bar chart.

I've set up a demo in jsfiddle with only 6 ethnic groups for now.

How do I only show the top 3 largest ethnic groups in my bar chart and hide the rest of the ethnic groups?

Example of my JSON data:

var myData = [{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"Name":"Gulran","Province":"Hirat","Ethnic1":0.19,"Ethnic2":0.32,"Ethnic3":"0.10","Ethnic4":"0.00","Ethnic5":"0.10","Ethnic6":"0.00"},"geometry":{"type":"Polygon","coordinates":[[[60.941162109375,29.897805610155874],[61.92993164062499,31.034108344903512],[63.34716796874999,31.3348710339506],[64.05029296875,30.401306519203583],[64.412841796875,29.735762444449076],[64.09423828125,29.36302703778376],[62.29248046875,29.36302703778376],[60.941162109375,29.897805610155874]]]}},{"type":"Feature","properties":{"Name":"Chahar Burjak","Province":"Nimroz","Ethnic1":0.25,"Ethnic2":0.12,"Ethnic3":0.03,"Ethnic4":0.01,"Ethnic5":"0.00","Ethnic6":"0.00"},"geometry":{"type":"Polygon","coordinates":[[[63.38012695312499,31.3348710339506],[65.06103515625,31.80289258670676],[65.6982421875,31.156408414557],[66.016845703125,30.467614102257855],[65.291748046875,30.164126343161097],[64.22607421875,30.0405664305846],[63.38012695312499,31.3348710339506]]]}}]}];

My D3 code:

var div = $('<div id="chart" style="width: 600px; height: 400px;"><svg></div>')[0];

        var popup = L.popup({minWidth: 600}).setContent(div);
        layer.bindPopup(popup);

        var values = feature.properties;
        var data = [
            {name:"Ethnic1",value:values["Ethnic1"]},
            {name:"Ethnic2",value:values["Ethnic2"]},
            {name:"Ethnic3",value:values["Ethnic3"]},
            {name:"Ethnic4",value:values["Ethnic4"]},
            {name:"Ethnic5",value:values["Ethnic5"]},
            {name:"Ethnic6",value:values["Ethnic6"]}
        ];

        var margin = {top: 20, right: 30, bottom: 40, left: 40},
            width = 600 - margin.left - margin.right,
            height = 400 - margin.top - margin.bottom,
            barHeight = height / data.length;

        var formatPercent = d3.format(".0%");


        var x = d3.scale.linear()
            .domain([0, d3.max(data, function(d){return d.value;})])
            .range([0, width]);
        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom")
            .tickFormat(formatPercent);

        var svg = d3.select(div).select("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
          .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .classed("chart", true);

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        var bar = svg.selectAll("g.bar")
            .data(data)
            .enter()
          .append("g")
            .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });

        bar.append("rect")
            .attr("width", function(d){return x(d.value);})
            .attr("height", barHeight - 1);

        bar.append("text")
            .attr("x", function(d) { return x(d.value) - 3; })
            .attr("y", barHeight / 2)
            .attr("dy", ".35em")
            .text(function(d) { return d.name; });

The way you do it is to first sort the data. Once you have sorted, you can filter the data to use only the top 3 values for creating the bar chart.

I have forked your fiddle. Here is the link https://jsfiddle.net/ankit89/x8u31jdo/

The important piece of code that I added/modifed are

       var sortedData = data.sort(function(a,b){
        return b.value - a.value;
       });

       //if you want to just keep top three
       sortedData = sortedData.filter(function(d,i){
        return i < 3;
       });

        var bar = svg.selectAll("g.bar")
            .data(sortedData)
            .enter()
            .append("g")
            .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });

Here is the Working Fiddle for you.

And the code used is as below

function GetTopThreeEthnic(arrayData){  //sorting to top 3 function
  arrayData.sort(function(a, b) {
                   return parseFloat(b.value) - parseFloat(a.value);
                 });
  return arrayData.slice(0, 3); 
}

And just make a call to this function after you initialize your data variable.

    var data = [
                    {name:"Ethnic1",value:values["Ethnic1"]},
                    {name:"Ethnic2",value:values["Ethnic2"]},
                    {name:"Ethnic3",value:values["Ethnic3"]},
                    {name:"Ethnic4",value:values["Ethnic4"]},
                    {name:"Ethnic5",value:values["Ethnic5"]},
                    {name:"Ethnic6",value:values["Ethnic6"]}
                ];                   
    data = GetTopThreeEthnic(data); // this is the code added

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM