-->

How to put data ranges in piecharts using dc.js?

2019-07-19 15:43发布

问题:

I have a pie chart for age, which currently has pie slices for every age there in the data set. Since the age range is wide, numerous thin slices are formed in the pie chart. I want to make it as a range, like one slice should show 0-18, another 19-30, and so on. How can I do this?

Here is my code

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="bower_components/dcjs/dc.css">
    <link rel="stylesheet" href="bower_components/leaflet/dist/leaflet.css">

    <script src="bower_components/d3/d3.min.js"></script>
    <script src="bower_components/crossfilter2/crossfilter.min.js"></script>
    <script src="bower_components/dcjs/dc.js"></script>

    <!--THE FOLLOWING META IS IMPORTANT, OTHERWISE THERE MIGHT BE A PROBLEM WITH SOME CHARACTERS--> 
    <meta http-equiv="content-type" content="text/html; charset=UTF8"> 
    <!--CDN FOR JQUERY-->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
</head>
<body>
    <div id="map">
        <a class="reset" href="javascript:usChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
        <span class="reset" style="display: none;"> | Current filter: <span class="filter"></span></span>
        <div class="clearfix"></div>
    </div>
    <div id="pie-gender">
        <a class="reset" href="javascript:usChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
        <span class="reset" style="display: none;"> | Current filter: <span class="filter"></span></span>
        <div class="clearfix"></div>
    </div>
    <div id="pie-age">
        <a class="reset" href="javascript:usChart.filterAll();dc.redrawAll();" style="display: none;">reset</a>
        <span class="reset" style="display: none;"> | Current filter: <span class="filter"></span></span>
        <div class="clearfix"></div>
    </div>
     <div>
        <a href="javascript:dc.filterAll(); dc.renderAll();">Reset All</a>
    </div>
    <script type="text/javascript">
        d3.csv("data/gender.csv", function (data) {
            d3.json("data/us-states.json", function (json){

                // set up crossfilter on the data.
                var ndx = crossfilter(data);

                // set up the dimensions
                var stateDim = ndx.dimension(function (d) { return d.state; });
                var genderDim = ndx.dimension(function(d) { return d.gender; });
                var ageDim = ndx.dimension(function(d) { return d.age; });

                //filtering age ranges
                var age_0_18 = ageDim.filter([0,19]);
                var age_19_30 = ageDim.filter([19,31]);
                var age_31_60 = ageDim.filter([31,61]);
                var age_61_101 = ageDim.filter([61,101]);


                // set up the groups/values
                var state = stateDim.group();
                var gender = genderDim.group(); 
                //var age = ageDim.group();
                var age1 = age_0_18.group();
                var age2 = age_19_30.group();
                var age3 = age_31_60.group();
                var age4 = age_61_101.group();

                // the different charts - options are set below for each one.
                var pieGender = dc.pieChart('#pie-gender');
                var pieAge = dc.pieChart('#pie-age')
                var usmap = dc.geoChoroplethChart("#map");

                //create pie to show gender
                pieGender
                    .width(180)
                    .height(180)
                    .radius(80)
                    .dimension(genderDim)
                    .group(gender)
                    .renderLabel(true)
                    .innerRadius(10)
                    .transitionDuration(500)
                    //.colorAccessor(function (d, i) { return d.value; });
                    //below is how to decide the colours for pie slices
                    .colors(d3.scale.ordinal().range([ '#14CAFF', '#4646FF']));

                //creating pie to show age
                pieAge
                    .width(180)
                    .height(180)
                    .radius(80)
                    .dimension(ageDim)
                    .group(age1,age2,age3,age4)
                    .renderLabel(true)
                    .innerRadius(10)
                    .transitionDuration(500)
                    .colorAccessor(function (d, i) { return d.value; });


                //display US map                    
                usmap
                    .width(900)
                    .height(500)
                    .dimension(stateDim)
                    .group(state)
                    .colors(["rgb(20,202,255)","rgb(70,70,255)"])
                    .overlayGeoJson(json.features, "name", function (d) { return d.properties.name; })      

                // at the end this needs to be called to actually go through and generate all the graphs on the page.
                dc.renderAll();
            }); 
        });             
    </script>
</body>

I tried using filter and then grouping, but the result remained the same. I think the procedure is wrong maybe.

Any help would be greatly appreciated. Thanks.

回答1:

I'm sure I've seen a lot of examples of this, but I couldn't find any in a quick search.

You'll want to use the group's groupValue function to put ages into the categories you want. This is exactly the same way you would round values down or do any other categorization:

var ageGroup = ageDim.group(function(v) {
  if(v < 19) return "18 or under";
  else if(v < 30) return "19-29";
  else if(v < 30) return "30-59";
  else return "over 60";
});

Note that dimension.filter() just returns the dimension and changes the filters for the entire crossfilter, so all of your groups above would be the same group, and only the last filter would take.