2017-09-19 4 views
1

J'essaie d'implémenter une visualisation de données en direct (c'est-à-dire avec de nouvelles données arrivant périodiquement) en utilisant dc.js. Le problème que j'ai est le suivant - quand de nouvelles données sont ajoutées à l'intrigue, les points déjà existants commencent souvent à "danser autour", même s'ils n'ont pas été changés. Cela peut-il être évité?dc.js - évite l'animation de points de données lors de l'ajout de données à un diagramme de dispersion

Le following fiddle illustre cela. Je suppose que crossfilter trie les données en interne, ce qui entraîne des points se déplaçant sur le graphique pour les éléments de données qui ont changé leur position (index) dans le stockage interne. Les données sont ajoutées de la façon suivante:

var data = []; 
var ndx = crossfilter(data) 
setInterval(function() { 
      var value = ndx.size() + 1; 
      if (value > 50) { 
       return; 
      } 
      var newElement = { 
       x: myRandom(), 
       y: myRandom() 
      }; 

      ndx.add([newElement]); 
      dc.redrawAll(); 
     }, 1000); 

Des idées?

+0

Je caractériserais un peu le problème: Les groupes et les dimensions du crossfilter renvoient toutes deux des données ordonnées, mais d3.js (quoi dc.js est construit sur) par défaut pour supposer que les points de données sont identifiés par leur index dans le tableau de données. Je pense que le nuage de points dc.js pourrait être mis à jour pour utiliser la clé de groupe comme index à la place? Pas certain. Cela devrait se produire ici, je crois: https://github.com/dc-js/dc.js/blob/develop/src/scatter-plot.js#L79 –

+0

merci pour la réponse! J'ai brièvement regardé dans la source, par mes compétences js ne sont pas assez ici. Je peux voir qu'il y a un commutateur disableTransitions, mais il bloque toutes les animations, ce qui rend les tracés légèrement rugueux. Pour mon projet actuel, désactiver les mouvements des points de données et conserver toutes les autres animations suffirait. Vous avez une idée de la façon de corriger le dc pour l'avoir? –

+0

Je ne suis pas sûr, mais théoriquement à partir d'une perspective d3.js, '.data (_chart.data());' deviendrait '.data (_chart.data(), fonction (d) {return d.something_unique_per_data_point}); Je pense que vous auriez accès à la clé de groupe à l'intérieur de cette fonction, donc vous pourriez l'utiliser. Je recommande d'ouvrir le problème dans le dépôt dc.js et de faire référence à cette discussion. –

Répondre

1

Je maintiens mes commentaires ci-dessus. dc.js devrait être corrigé en liant les données en utilisant une fonction clé, et probablement la meilleure façon de traiter le problème est simplement de désactiver les transitions sur le nuage de points en utilisant .transitionDuration(0)

Cependant, j'étais curieux de savoir s'il était possible de travailler autour des problèmes actuels en gardant le groupe dans un ordre déterminé en utilisant un groupe faux. Et il est en effet, au moins pour cet exemple où il n'y a pas d'agrégation et nous voulons juste afficher les points de données d'origine.

D'abord, nous ajoutons un troisième champ, index, aux données. Cela doit ordonner les données dans le même ordre que celui dans lequel elles entrent. Comme indiqué dans la discussion ci-dessus, le nuage de points lie actuellement les données par son index, nous devons donc conserver les points dans un ordre déterminé; rien ne devrait être inséré.

 var newElement = { 
     index: value, 
     x: myRandom(), 
     y: myRandom() 
     }; 

Ensuite, nous devons préserver cet indice par le binning et l'agrégation. Nous pourrions garder soit dans la clé ou de la valeur, mais en gardant dans la clé semble plus approprié:

 xyiDimension = ndx.dimension(function(d) { 
     return [+d.x, +d.y, d.index]; 
     }), 
     xyiGroup = xyiDimension.group(); 

La réduction originale n'a pas de sens pour moi, donc je l'ai abandonné. Nous allons simplement utiliser le comportement par défaut, qui compte le nombre de lignes qui tombent dans chaque bin. Les chiffres devraient être 1 si inclus, ou 0 si filtré. L'inclusion de l'index dans la clé assure également l'unicité, ce qui n'était pas garanti pour les clés d'origine.

Maintenant, nous pouvons créer un groupe faux qui maintient tout triés par index:

var xyiGroupSorted = { 
     all: function() { 
     var ret = xyiGroup.all().slice().sort((a,b) => a.key[2] - b.key[2]); 
     return ret; 
     } 
    } 

Cela parcoura les données d'origine chaque fois qu'il est demandé par le tableau, créez une copie du tableau (parce que le appartiennent à des intérêts d'origine par crossfilter), et le trier pour le renvoyer dans le bon ordre. Et voilà, nous avons un nuage de points qui se comporte comme il se doit, même si les données ont traversé le filtre croisé.

Fourchette de votre violon: https://jsfiddle.net/gordonwoodhull/mj81m42v/13/

[Après tout cela, peut-être que nous ne devrions pas avoir donné les données à crossfilter en premier lieu! Nous aurions pu créer un faux groupe qui expose les données d'origine. Mais peut-être y a-t-il un intérêt à cette technique. Au moins cela prouve qu'il y a presque toujours un moyen de contourner les problèmes dans le crossfilter dc.js &.]