2012-11-28 13 views
21

Chciałbym wiedzieć, czy istnieje łatwy sposób modyfikacji Sankey diagram example, aby zapewnić płynne przejście do nowych danych. Na przykład, wyobraź sobie, że mam różne pliki danych (energy1.json, energy2.json ...) w jaki sposób d3 może narysować wykres Sankeya dla pierwszego zestawu danych, a następnie czeka, a następnie na tylnych ustawieniach pól, w celu przedstawienia drugiego zestawu danych?Przejście diagramu Sankey'a

+0

Czy kiedykolwiek rozwiązać ten problem? – PhoebeB

+1

Czy wszystkie twoje pliki danych mają te same węzły, ale różne przepływy między nimi? – ASGM

Odpowiedz

14

To jest możliwe. Oto jedna z metod korzystania z pliku csv. Praca Sankey tutaj: https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

  1. Zdefiniuj globalną tablicę poza rozmowy d3.csv.

    var portfolioValues = []; 
    
  2. Podczas analizowania CSV, aby utworzyć strukturę węzeł/link, pchania wartości do globalnej tablicy.

    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. Posłuchaj zmiany i wprowadź dane użytkownika do funkcji aktualizacji.

    $(".sankey-slider").bind("slider:changed", function (event, data) { 
    
    slideValue = data.value; 
    
    updateData(parseInt(slideValue)); 
    
    }); 
    
  4. Utwórz tymczasową tablicę i pobierz poprawne wartości z tablicy globalnej. Zadzwoń do funkcji sankey, aby ponownie obliczyć układ.

    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. Wybierz każdy element, który należy zmienić i podaj nowe wartości danych.

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

Praca SANKEY tutaj: https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

+0

Hi @ Joe-Jansen jest tam jsfiddle z kodem. Niezwykle przydatne będzie mieć otoczenie do rozwidlenia i dostrojenia w razie potrzeby. – lwall

2

Ponieważ automatyczne pozycjonowanie węzłów obejmuje część, która próbuje zminimalizować odległość łącza na podłączonym wykresie, co jest np. Problemem optymalizacyjnym, każdy rodzaj optymalizatora może potencjalnie przeskakiwać z jednego minimum na drugi, prowadząc do skoku układu. Gwarantowane płynne przejście nie będzie możliwe.

Najbliższym możliwym rozwiązaniem byłoby prawdopodobnie interpolacja liniowa między dwoma zestawami danych wejściowych i wygenerowanie w ten sposób szeregu wykresów, które (w zależności od danych) mniej lub bardziej płynnie przechodzą od siebie nawzajem.

Mam nadzieję, że to pomoże.

+0

Czy możesz dodać przykład na jsfiddle? To byłoby bardzo pomocne! – lwall