How to create a group from a group in crossfilter/reductio?

With the following data:

const now = new Date
const data = [
  { player: 'bob', color: 'blue', date: new Date(+now + 1000) },
  { player: 'bill', color: 'green', date: new Date(+now + 2000) },
  { player: 'bob', color: 'red', date: new Date(+now + 3000) },
  { player: 'barbara', color: 'blue', date: new Date(+now + 4000) },
  { player: 'barbara', color: 'cyan', date: new Date(+now + 8000) },
  { player: 'barbara', color: 'magenta', date: new Date(+now + 10000) },
  { player: 'barbara', color: 'yellow', date: new Date(+now + 20000) },
]

I want to reduceCount on the color dimension, but only count the first color per-player. (note: first is wrt the date dimension which may be filtered). I have been trying to get this to work with reductio using the exception feature but it did not give the expected results:

reducer = reductio()
reducer.exception('player').exceptionCount(true)
reducer(colorGroup)

The results should look like this:

blue,2     # bob and barbara
cyan,0
green,1    # bill
magenta,0
red,0
yellow,0

Another example, with the date dimension filtered to now+2100 .. now+20000 (ie the first row is filtered out):

blue,1     # barbara
cyan,0
green,0    # (bill's first color is not counted because it is outside the date range)
magenta,0
red,1      # bob (blue is his first color overall, red is his first in this date range)
yellow,0

Note: I have other groupings which use all of the rows so I can't just pre-filter the list before loading it into crossfilter.

Is there some way to use reductio() for this? Or some example of how to do this "grouping upon grouping" with crossfilter directly?

EDIT

Link to jsfiddle showing unexpected result: https://jsfiddle.net/qt5jxjm1/


I'm not sure if crossfilter is going to help you very much here - it doesn't really consider the order of values, and it certainly doesn't have a way to sort by one key and then bin by another.

Here is a fake group that will do close to what you want, by using another dimension for ordering, and a couple of accessors for the group key and the "first field", ie the field you want to look for the first of:

function double_reduce(dim, groupf, firstf) {
    return {
      all: function() {
      var recs = dim.bottom(Infinity);
      var hit = {}, bins = {};
      recs.forEach(function(r) {
        var fkey = firstf(r), gkey = groupf(r);
        var count = hit[fkey] ? 0 : 1;
        hit[fkey] = true;
        bins[gkey] = (bins[gkey] || 0) + count;
      });
      return Object.keys(bins).map(function(k) {
        return {key: k, value: bins[k]};
      });
    }
  }
}

Use it like this:

var dubred_group = double_reduce(dateDim,
    function(r) { return r.color;}, function(r) { return r.player; });

One thing this can't do is deliver zeros for any values that are filtered out. Ordinarily crossfilter does incremental adds and removes and I don't see how that would be possible here.

So the results without any dates filtered look good:

[
  {
    "key": "blue",
    "value": 2
  },
  {
    "key": "green",
    "value": 1
  },
  {
    "key": "red",
    "value": 0
  },
  {
    "key": "cyan",
    "value": 0
  },
  {
    "key": "magenta",
    "value": 0
  },
  {
    "key": "yellow",
    "value": 0
  }
]

But there is a missing bin for the filtered case, because green does not appear in the filtered data:

[
  {
    "key": "red",
    "value": 1
  },
  {
    "key": "blue",
    "value": 1
  },
  {
    "key": "cyan",
    "value": 0
  },
  {
    "key": "magenta",
    "value": 0
  },
  {
    "key": "yellow",
    "value": 0
  }
]

This could probably be fixed, but I thought I would post this for feedback.

Demo in a fiddle: http://jsfiddle.net/zdq4rj13/7/

链接地址: http://www.djcxy.com/p/32816.html

上一篇: Crossfilter条形图不呈现

下一篇: 如何从crossfilter / reductio的组中创建一个组?