Search code examples
dc.jscrossfilter

dc.js add up only some values in numberDisplay


For the numberDisplay I only see examples in which all values are summed. But I would like to apply a filter so that I only see the values for a certain type.

In the example JSFIDDLE there is now a numberDisplay where all values are summed.

Is it also possible to only summarize the values of which for example the type is "cash"?

So in this case I would like to see the number 6 if nothing is selected.

Thank you in advance for your help.

HTML

<div id="demo1">
<h2>Markers with clustering, popups and single selection</h2>
<i>Renewable energy plants in Bulgaria in 2012</i>
<div class="lineChart"></div>
<div class="pie"></div>
<h5>I want here onlny the total number for type "cash" (nothing selected 6)</h5>
<div class="number_cash"></div>
</div>

<pre id="data">date type    value
  1/1/2020  cash    1
  1/1/2020  tab 1
  1/1/2020  visa    1
  1/2/2020  cash    2
  1/2/2020  tab 2
  1/2/2020  visa    2
  1/3/2020  cash    3
  1/3/2020  tab 3
  1/3/2020  visa    3
 </pre>

JavaScript

    function drawMarkerSelect(data) {
  var xf = crossfilter(data);

  const dateFormatSpecifier = '%m/%d/%Y';
  const dateFormat = d3.timeFormat(dateFormatSpecifier);
  const dateFormatParser = d3.timeParse(dateFormatSpecifier);

  data.forEach(function(d) {
    var tempDate = new Date(d.date);
    d.date = tempDate;
  })


  var groupname = "marker-select";
  var facilities = xf.dimension(function(d) {
    return d.date;
  });
  var facilitiesGroup = facilities.group().reduceSum(d => +d.value);

  var typeDimension = xf.dimension(function(d) {
    return d.type;
  });
  var typeGroup = typeDimension.group().reduceSum(d => +d.value);

  var dateDimension = xf.dimension(function(d) {
    return d.date;
  });
  var dateGroup = dateDimension.group().reduceSum(d => +d.value);

  var minDate = dateDimension.bottom(1)[0].date;
  var maxDate = dateDimension.top(1)[0].date;

  //numberDisplay cash
  var all = xf.groupAll();
  var ndGroup = all.reduceSum(function(d) {
    return d.value; //6
  });

  //numbers
  var number_cash = dc.numberDisplay("#demo1 .number_cash", groupname)
    .group(ndGroup)
    .valueAccessor(function(d) {
      return d;
    });

  var pie = dc.pieChart("#demo1 .pie", groupname)
    .dimension(typeDimension)
    .group(typeGroup)
    .width(200)
    .height(200)
    .renderLabel(true)
    .renderTitle(true)
    .ordering(function(p) {
      return -p.value;
    });

  var lineChart = dc.lineChart("#demo1 .lineChart", groupname)
    .width(450)
    .height(200)
    .margins({
      top: 10,
      bottom: 30,
      right: 10,
      left: 70
    })
    .dimension(dateDimension)
    .group(dateGroup, "total spend")
    .yAxisLabel("Transaction spend")
    .renderHorizontalGridLines(true)
    .renderArea(true)
    .legend(dc.legend().x(1200).y(5).itemHeight(12).gap(5))
    .x(d3.scaleTime().domain([minDate, maxDate]));

  lineChart.yAxis().ticks(5);
  lineChart.xAxis().ticks(4);

  dc.renderAll(groupname);
}

const data = d3.tsvParse(d3.select('pre#data').text());

drawMarkerSelect(data);

CSS

  pre#data {
    display: none;
  }

  .marker-cluster-indiv {
    background-color: #9ecae1;
  }

  .marker-cluster-indiv div {
    background-color: #6baed6;
  }

Solution

  • Crossfilter is a framework for mapping and reducing in JavaScript. The dimension and group key functions determine the mapping to group bins, and the group reduce functions determine how to add or remove a row of data to/from a bin.

    When you use a groupAll, there is just one bin.

    With that in mind, you can count cash rows at face value, and count other rows as zero, by writing your reduceSum function as

      var ndGroup = all.reduceSum(function(d) {
        return d.type === 'cash' ? d.value : 0;
      });
    

    Fork of your fiddle.