0
votes

I have two dc.barCharts and two dc.NumberDisplays.

JS Fiddle is here: https://jsfiddle.net/wgbruqk8/6/ .

One of the number displays shows the total of the overall population that is selected. The other currently shows the fraction of all other dimensions that are selected -- I'd like for it to show the fraction of the dimension at hand that is selected. For example, since its dimension is Achievement, if the brush is at [10,90], I'd like for it to show 100%. However, if the brush is at [31, 90], I'd like for it to show 90% because there are 11 total cases and the brush is over 10 of them. How do I have it show the proportion of cases that the brush has selected?

Also including the JS below:

data = [{'achievement': 30,'balance': 35}, 
                {'achievement': 46, 'balance': 35},
        {'achievement': 72, 'balance': 33},
        {'achievement': 50, 'balance': 29},
        {'achievement': 55, 'balance': 38},
        {'achievement': 70, 'balance': 40},
        {'achievement': 85, 'balance': 42},
        {'achievement': 80, 'balance': 41},
        {'achievement': 46, 'balance': 35},
        {'achievement': 46, 'balance': 35},
        {'achievement': 46, 'balance': 35},];

console.log(data);

var chartMargins = {top: 10, right: 30, bottom: 20, left: 40};

var ndx = crossfilter(data),
    all = ndx.groupAll(),
    countAll = all.reduceCount(),

    achievement = ndx.dimension(function(d) {
          return d.achievement;
        }),
    achievementGroup = achievement.group(Math.floor),
    balance = ndx.dimension(function(d) {
          return d.balance;
        }),
    balanceGroup = balance.group(Math.floor);


var achievementChart = dc.barChart('#dc-achievement-chart')
            .width(600)
            .height(80)
            .margins(chartMargins)
            .dimension(achievement)
            .group(achievementGroup)
          .x(d3.scale.linear().domain([0,100]));

var balanceChart = dc.barChart('#dc-balance-chart')
            .width(700)
            .height(80)
            .margins(chartMargins)
            .dimension(balance)
            .group(balanceGroup)
            .centerBar(true)
          .x(d3.scale.linear().domain([0,100]).rangeRound([0, 10*100]))
            .filter([40,100]);

dc.numberDisplay('#dc-overall-total')
      .width(100)
      .valueAccessor(function(d) { return d / 11})
      .formatNumber(d3.format('%'))
      .group(ndx.groupAll());

dc.numberDisplay('#dc-achievement-selection')
     .valueAccessor(function(d) { return d / 11})
     .formatNumber(d3.format('%'))
     .group(achievement.groupAll());

dc.renderAll();
1
So you need a count of the number of records that would be in the filter if only one dimension were filtered?Ethan Jewett
Yes. The docs for groups say ": a grouping intersects the crossfilter's current filters, except for the associated dimension's filter. Thus, group methods consider only records that satisfy every filter except this dimension's filter." Basically, I want the opposite of that -- I want to only consider the records that satisfy the dimension's filter.orange1
Yeah, understood. For this simple case, I think the best approach would be to just do the calculation on the raw data outside of Crossfilter. However, since this type of metadata on a dimension is information that is actually quite important and useful for visualization apps, maybe it is something we should think about adding to Crossfilter. Could you create an issue in the Crossfilter project? github.com/crossfilter/crossfilterEthan Jewett
Great idea, will do, @ethan-jewett .orange1

1 Answers

2
votes

As mentioned above, you currently probably have to do this calculation against the raw data, based on filters pulled from your dc.js chart. Here is an example of how to do it: https://jsfiddle.net/jy8zh18a/1/

The key is basically to create a fake group and calculate the number of data elements that match the current filter on whatever chart you are interested in:

var acheivementSelectGroup = {
  value: function() {
    var acheivementFilter = achievementChart.filter();
    var selectedValues = data.filter(function(d) {
        if(acheivementFilter) {
        return acheivementFilter[0] <= d['achievement'] &&
            d['achievement'] <= acheivementFilter[1];
      } else {
        return true;
      }
    }).length;
    return selectedValues;
  }
}

Then use that fake group in your number display:

dc.numberDisplay('#dc-achievement-selection')
     .valueAccessor(function(d) { return d / 11})
     .formatNumber(d3.format('%'))
     .group(acheivementselectyroup);

Note in the code above, 'achievement' is spelled in 2 different ways based on the different spellings in the chart variable name and the data attribute. Not critiquing spelling here, but just pointing it out as it might be confusing to others coming at this problem :-)