2012-11-28 85 views
21

我想知道是否有修改Sankey diagram example以便有新數據平滑過渡的簡單方法。例如,假設我有不同的數據文件(energy1.json,energy2.json ......)怎麼會D3繪製的第一個數據集的平衡圖,然後等待後來就rearanges框配置來表示第二個數據集?熱平衡圖過渡

+0

你有沒有解決這個問題? – PhoebeB

+1

你所有的數據文件都有相同的節點,但它們之間有不同的流程? – ASGM

回答

14

這是可能的。以下是使用csv文件的一種方法。工作桑基這裏:https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

  1. 定義你d3.csv通話之外的全球陣列。

    var portfolioValues = []; 
    
  2. 解析csv以創建節點/鏈接結構時,將值推送到您的全局數組。

    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. 聽取更改並將用戶輸入傳遞到更新函數。

    $(".sankey-slider").bind("slider:changed", function (event, data) { 
    
    slideValue = data.value; 
    
    updateData(parseInt(slideValue)); 
    
    }); 
    
  4. 創建一個臨時數組並從全局數組中檢索正確的值。調用sankey函數重新計算佈局。

    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. 選擇每個需要更改的元素並傳遞新的數據值。

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

工作桑基這裏: https://www.betterment.com/resources/investment-strategy/portfolio-management/portfolio-diversification/

+0

喜@喬 - 詹森是有你的代碼的jsfiddle。如果需要的話,有一個環境來分叉和調整是非常有用的。 – lwall

2

由於節點的自動定位包括試圖最小化在連接圖,其是一個NP優化問題鏈路距離的一部分,任何種類的優化器可潛在地從一個最小跳到另一個導致佈局跳躍。所以保證平穩過渡不會成爲可能。

的最接近的可能解決方案可能會在兩個輸入數據集之間的線性插入,並由此產生了一系列(取決於數據)或多或少平滑地從一個兩個其它過渡圖形。

希望這會有所幫助。

+0

你可以在jsfiddle上添加一個例子嗎?這會非常有幫助! – lwall