2 votes

Comment créer un groupe à partir d'un groupe dans crossfilter/reductio ?

Avec les données suivantes :

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) },
]

Je veux réduire le nombre sur la dimension de la couleur, mais seulement comptez la première couleur par joueur. (note : la première est par rapport à la dimension de la date qui peut être filtrée). J'ai essayé de faire fonctionner ceci avec reductio en utilisant la fonction exception mais cela n'a pas donné les résultats escomptés :

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

Les résultats devraient ressembler à ceci :

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

Un autre exemple, avec la dimension date filtrée à now+2100 .. now+20000 (c'est-à-dire que la première ligne est filtrée) :

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

Remarque : j'ai d'autres regroupements qui utilisent toutes les lignes, donc je ne peux pas simplement pré-filtrer la liste avant de la charger dans crossfilter.

Y a-t-il un moyen d'utiliser reductio() pour cela ? Ou un exemple de comment faire ce "regroupement sur regroupement" avec crossfilter directement ?

EDIT

Lien vers jsfiddle montrant un résultat inattendu : https://jsfiddle.net/qt5jxjm1/

2voto

Gordon Points 12563

Je ne suis pas sûr que le filtre croisé vous soit d'une grande aide ici - il ne prend pas vraiment en compte l'ordre des valeurs, et il n'a certainement pas la possibilité de trier par une clé puis de classer par une autre.

Voici un faux groupe qui se rapproche de ce que vous voulez, en utilisant une autre dimension pour l'ordonnancement, et quelques accesseurs pour la clé du groupe et le "premier champ", c'est-à-dire le champ dont vous voulez rechercher le premier :

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]};
      });
    }
  }
}

Utilisez-le comme ça :

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

Une chose que cela ne peut pas faire est de fournir des zéros pour toutes les valeurs qui sont filtrées. D'habitude, le filtre croisé fait des ajouts et des retraits incrémentiels et je ne vois pas comment cela serait possible ici.

Ainsi, les résultats sans aucune date filtrée semblent bons :

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

Mais il y a une case manquante pour le cas filtré, car le vert n'apparaît pas dans les données filtrées :

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

Cela pourrait probablement être corrigé, mais j'ai pensé que je posterais ceci pour avoir un retour.

Démonstration dans un violon : http://jsfiddle.net/zdq4rj13/7/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X