Search code examples
dc.jscrossfilterreductio

geoChoroplethChart is black with two option of value for one key


I have the next data works with dc.js and geoChoroplethChart,

var data = crossfilter([
{ state: 'one', bar: 'A', num: '1' },
{ state: 'two', bar: 'B', num: '2' },
{ state: 'three', bar: 'A', num: '3' },
{ state: 'one', bar: 'B', num: '3' },
{ state: 'one', bar: 'A', num: '2' },
{ state: 'two', bar: 'B', num: '2' },
]);


var statedim=data.dimension(function(d){return d['state'];})
var my_group=statedim.group();

reducer=reductio();
reducer.value('nbar').exception(function(d){return d['bar']}.exceptionCount(true);
reducer.value('nnum').exception(function(d){return d['num']}.exceptionCount(true);


reducer(my_group);

where state is a region in my country and the color is based on nnum, so I use

.valueAccessor(function (d) {return d.value.nnum.exceptionCount})

but I want it in the title appear state, nnum and nbar.

.title(function(d){
return["state: " +d.key,
"#nnum: "+d.value].join('\n')})

but I do not know how to integrate nbar in title without geoChoroplethChart is black.

I think in use

.valueAccessor(function (d) {return d.value})

.title(function(d){
return["state: " +d.key,
"#nnum: "+d.value.nnum.exceptionCount,
"nbar:" +d.value.nbar.exceptionCount].join('\n')})

It is the solution for the title, but the states fill up black and when I click on another graphic, the map does not react.


Solution

  • The way the geoChoropleth deals with data is definitely pretty weird. All the other charts bind the crossfilter data to the SVG; geoChoropleth binds the map data and hides the crossfilter data in an internal object. Then it fakes bound data for the accessors.

    What's more, as you point out, it stores the result of the valueAccessor() in its hidden data, rather than binding the raw data and then using the valueAccessor when needed. I'm pretty sure that's a bad idea.

    But enough complaining. Let's find the workaround, as usual.

    Turns out you don't need to drill down in the value accessor in order to get the colors right. You can leave the valueAccessor defaulted, and it will fetch d.value. Then use the colorAccessor to get the colors right:

    .colorAccessor(function(d){
      return d ? d.nbar.exceptionCount : null;
    })
    

    Note the guard against undefined data, a result of the same weirdness.

    We also need to guard against an undefined value in the title accessor, because the chart is building key/value pairs from the map data, not the crossfilter data:

    .title(function(d){
      var arr = ["state: " + d.key];
      if(d.value) // have to guard against null data for "other" states
        arr.push(
         "#nnum: "+d.value.nnum.exceptionCount,
         "nbar:" +d.value.nbar.exceptionCount
        );
      return arr.join('\n');
    })
    

    Fork of your fiddle: https://jsfiddle.net/gordonwoodhull/7qb3yujj/14/