1
votes

I have a dimension which returns 2 categories, the two values can also be sub-categorized into 3 each. I want to display a pie chart with only 3 slices from one of the categories. Every time i try it gives me one dimension but the total count of the group is greater than any one categories and is in fact the total of the entire dimension. Any ideas??

Below is my code dimension:

eidDimension = ndx.dimension(function(d){
                  y = d.message;


                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Positive") > -1)){

                        return "Positive";
                    }
                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Negative") > -1)){

                        return "Negative";
                    }
                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Invalid") > -1)){

                        return "Invalid";
                    }

                })

The group:

eidCountGroup = eidDimension.group().reduceCount(function(d){

                  y = d.message;


                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Positive") > -1)){

                        return +y;
                    }
                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Negative") > -1)){

                        return +y;
                    }
                    if((y.indexOf("FFEID") > -1) && (y.indexOf("Invalid") > -1)){

                        return +y;
                    }

                })

the pie chart:

  eidchart
                     .width(width)
                     .height(300)
                     .slicesCap(5)
                     .innerRadius(20).colors(d3.scale.category10())
                     .dimension(eidDimension)
                     .group(eidCountGroup)
                     .legend(dc.legend())
                     .on('pretransition', function(chart) {
                     chart.selectAll('text.pie-slice').text(function(d) {
                             return d.data.key + ' ' + dc.utils.printSingleValue((d.endAngle - d.startAngle) / (2*Math.PI) * 100) + '%';
                     })
                     });

                 eidchart.render();

Now the d.message has strings which include "FFViral" which i dont want included in the pie chart. The totals i get from the pie chart however means that they are being included.

Here is a sample of the data.

[
  {
    "id": 3071,
    "result_id": "361a3a26-feb7-4aa7-bd12-195fa35b45b0",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:11637-00048 Result: :10565 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T08:37:04.060+0000",
    "time_stamp": "2017-04-12 12:06:48",
    "notified": 0
  },
  {
    "id": 3072,
    "result_id": "8354210c-9ab4-41a3-8104-77a15d9dd338",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFEID Results   Patient ID:11637-00048 Result: :Negative Approved by : Supervisor",
    "date": "2017-04-12T08:36:53.250+0000",
    "time_stamp": "2017-04-12 12:06:48",
    "notified": 0
  },
  {
    "id": 3073,
    "result_id": "3d992dc1-a298-4ce4-a1bf-008b0d179a6e",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFEID Results   Patient ID:51334602107 Result: :Negative Approved by : Supervisor",
    "date": "2017-04-12T08:36:52.417+0000",
    "time_stamp": "2017-04-12 12:06:48",
    "notified": 0
  },
  {
    "id": 3074,
    "result_id": "fde8313c-da15-467a-9cb9-c366426214f2",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFEID Results   Patient ID:11637-00048 Result: :Positive Approved by : Supervisor",
    "date": "2017-04-12T09:20:15.740+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3075,
    "result_id": "a492b14d-147b-4387-89d4-b5d5acb44c5f",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:11637-00002 Result: :292742 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T09:19:26.703+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3076,
    "result_id": "2455a23c-3691-41f8-91e0-d8c7f811b695",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:11637-00024 Result: :33597 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T09:19:25.860+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3077,
    "result_id": "448c797b-996f-4e0f-9b19-003566c0b671",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFEID Results   Patient ID:11637-00048 Result: :Invalid Approved by : Supervisor",
    "date": "2017-04-12T09:19:24.960+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3078,
    "result_id": "f142944b-aa48-43bd-80e7-7a6483ea6282",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:1163700018 Result: :246796 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T09:19:22.033+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3079,
    "result_id": "d9889930-93a3-48ab-97cd-1fa1063b52d6",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:1163700032 Result: :3726 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T09:19:21.207+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3080,
    "result_id": "1fcdb8ea-63d7-4e9f-99ee-02912e2c501f",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:11637-00039 Result: :5691 cp/mL Approved by : Supervisor",
    "date": "2017-04-12T09:19:20.353+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3081,
    "result_id": "b580b875-6d2a-4995-ba6f-021ce319cb6e",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:50100100125 Result: :< LDL copies/ml  Approved by : Supervisor",
    "date": "2017-04-12T09:19:16.580+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3082,
    "result_id": "5e6eb9d2-6b2e-49d6-883b-86152fce5a44",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:11637-30600100379 Result: :< LDL copies/ml  Approved by : Supervisor",
    "date": "2017-04-12T09:19:15.643+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3083,
    "result_id": "6793be3c-25b1-431d-a164-faeb405d6fe6",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:1163700040 Result: :< LDL copies/ml  Approved by : Supervisor",
    "date": "2017-04-12T09:19:11.820+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  },
  {
    "id": 3084,
    "result_id": "2c10407f-3c8b-40de-af28-5cc295fbba0e",
    "phone_no": 726974003,
    "status": 0,
    "message": "FFViral Load Results   Patient CCC #:1163-00044 Result: :< LDL copies/ml  Approved by : Supervisor",
    "date": "2017-04-12T09:19:07.010+0000",
    "time_stamp": "2017-04-12 12:26:40",
    "notified": 0
  }
]

I want to show a pie chart of the data where message contains only "FFEID" as Positive, negative or invalid and leave out the "FFViral" messages from the piechart.

1
Please share some code!Mazz
@Mazz thank you. I did forgive my inexperience.Ronnie Oduor
the reduceCount function looks pretty weird - it does string matching on y and then converts it to a number. are you sure that's what you want? seems like you'll just get NaN every time.Gordon
Does group.reduceCount even take an argument? But I'm concerned about the dimension accessor. There are a lot of potential situations in which that will return null and break everything. Sharing either data or a working example with sample data would be helpful as far as getting to an answer.Ethan Jewett
@Gordon i am not getting NaN but I'm not sure about it.Ronnie Oduor

1 Answers

1
votes

I think you'll need to use a fake group for this.

Usually all charts in dc.js/crossfilter contain all the data, except that which is filtered. If you want to exclude some data without filtering it in the other charts, you need to post-process the data.

What is happening

First let me explain what I think is currently happening. Your eidDimension function returns Positive, Negative, or Invalid if the message contains FFEID, but what does it return if the message doesn't contain the string?

In JavaScript, functions always have to return something, so if a function gets to the end and there is no explicit return, it returns undefined.

So you are probably ending up with 4 categories there, one with the key undefined.

How to exclude values

So let's correct that first. We'll make the fourth category explicit:

eidDimension = ndx.dimension(function(d){
              y = d.message;


                if((y.indexOf("FFEID") > -1) && (y.indexOf("Positive") > -1)){

                    return "Positive";
                }
                if((y.indexOf("FFEID") > -1) && (y.indexOf("Negative") > -1)){

                    return "Negative";
                }
                if((y.indexOf("FFEID") > -1) && (y.indexOf("Invalid") > -1)){

                    return "Invalid";
                }

             return 'non-FFEID'; // make 4th category explicit
            })

Now we can exclude that fourth category using a fake group from the FAQ:

function remove_bins(source_group) { // (source_group, bins...}
    var bins = Array.prototype.slice.call(arguments, 1);
    return {
        all:function () {
            return source_group.all().filter(function(d) {
                return bins.indexOf(d.key) === -1;
            });
        }
    };
}

eidCountGroup = remove_bins(eidDimension.group(), 'non-FFEID');

This takes a crossfilter group and wraps it in an object which implements .all() by calling the crossfilter group's .all() and then removes any bins given as arguments.

Note that we don't need to specify reduceCount or a function for it. As @Ethan pointed out, reduceCount doesn't take any parameters, so that function was getting ignored. reduceCount is also the default reduction so there's no need to call it at all.

Caveats

Despite looking kind of hacky, fake groups work pretty well. This is because dc.js only uses a tiny portion of the crossfilter API.

However, using crossfilter this way may produce some unexpected results.

  1. If someone clicks on a slice, say Negative in the FFEID pie chart, they will filter all of the charts on both FFEID and Negative. That might be confusing unless the chart is clearly marked.
  2. If someone clicks on another chart causing FFEID to be filtered out (say FFViral) then this chart will become completely empty, because all matching rows now are in the non-FFEID category. This makes sense if you think about it, but it's different from other dc.js charts where each chart represents all of the data in some way.