Transition du diagramme de Sankey

je voudrais savoir si il existe un moyen facile de modifier l' exemple de diagramme de Sankey de sorte qu'il y ait une transition en douceur vers les nouvelles données. Par exemple, imaginez que j'ai différents fichiers de données (energy1.JSON, energy2.json ...) comment d3 pourrait-il tracer un diagramme de Sankey pour le premier ensemble de données, puis attend et modifie plus tard la disposition des boîtes pour représenter le deuxième ensemble de données?

21
demandé sur VividD 2012-11-28 15:19:33

2 réponses

C'est possible. Voici une approche utilisant un fichier csv. Travailler sankey ici: https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

  1. définissez un tableau global en dehors de votre d3.appel csv.

    var portfolioValues = [];
    
  2. lors de l'analyse du csv pour créer la structure noeud/lien, poussez les valeurs vers votre tableau global.

    d3.csv("etf-geo.csv", function(error, data) {
        graph = {"nodes" : [], "links" : []};
        data.forEach(function (d, i) {
            var item = { source: d.source, target: d.target, values: [] };
            for (var j=0; j < 101; j++) {
                item.values.push(d['value'+j.toString()]);
            }
            portfolioValues.push(item);
            graph.nodes.push({ "name": d.source });
            graph.nodes.push({ "name": d.target });
            graph.links.push({
                source: portfolioValues[i].source,
                target: portfolioValues[i].target,
                value: portfolioValues[i].values[startingAllocation]
            });
        });
    
    //this handy little function returns only the distinct / unique nodes
    graph.nodes = d3.keys(
        d3.nest()
            .key(function (d) { return d.name; })
            .map(graph.nodes)
    );
    
    // it appears d3 with force layout wants a numeric source and target
    // so loop through each link replacing the text with its index from node
    graph.links.forEach(function (d, i) {
        graph.links[i].source = graph.nodes.indexOf(graph.links[i].source);
        graph.links[i].target = graph.nodes.indexOf(graph.links[i].target);
        portfolioValues[i].source = graph.links[i].source;
        portfolioValues[i].target = graph.links[i].target;
    });
    
    // now loop through each nodes to make nodes an array of objects
    // rather than an array of strings
    graph.nodes.forEach(function (d, i) {
        graph.nodes[i] = { "name": d };
    });
    
    // construct sankey
    sankey
        .nodes(graph.nodes)
        .links(graph.links)
        .layout();
    
  3. écoutez pour changer et passez l'entrée de l'utilisateur à votre fonction de mise à jour.

    $(".sankey-slider").bind("slider:changed", function (event, data) {
    
    slideValue = data.value;
    
    updateData(parseInt(slideValue));
    
     });
    
  4. créer un tableau temporaire et récupérer les valeurs correctes à partir du tableau global. Appeler les fonctions sankey pour recalculer la mise en page.

        var newLinks = [];
    
        portfolioValues.forEach(function(p, i) {
            newLinks.push({
              source: p.source,
              target: p.target,
              value: p.values[allocation]
            });
        });
    
        graph.links = newLinks;
    
        sankey
        .nodes(graph.nodes)
        .links(graph.links)
        .size([width, height])
        .layout();
    
  5. Sélectionnez chaque élément qui doit être changé et pass les nouvelles valeurs de données.

    d3.selectAll(".link")
      .data(graph.links)
      .attr("d", path)
      .attr("id", function(d,i){
        d.id = i;
        return "link-"+i;
      })
      .style("stroke-width", function(d) { return Math.max(1, d.dy); })
      .sort(function(a, b) { return b.dy - a.dy; });
    
    d3.selectAll(".node").attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")"; });
    
    d3.selectAll("rect")
    .attr("height", function(d) { return d.dy; })
    .on("mouseover",highlight_node_links)
    .on("mouseout",onNodeMouseout);
    

Travail sankey ici: https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

14
répondu Joe Jansen 2016-11-22 14:58:21

comme le positionnement automatique des noeuds inclut une partie qui essaie de minimiser la distance de liaison dans un graphe connecté qui est un problème d'optimisation np, tout type d'optimiseur peut potentiellement passer d'un minimum à un autre conduisant à un saut dans la mise en page. Une transition en douceur garantie ne sera donc pas possible.

la solution la plus proche serait probablement d'interpoler linéairement entre les deux séries de données d'entrée et de générer ainsi une série de graphiques qui (en fonction de la données) plus ou moins en douceur la transition de l'un à l'autre.

J'espère que cela vous aidera.

2
répondu Cornelius 2013-03-12 10:11:40