2012-09-13 69 views
3

我使用d3.nest()爲了從CSV文件中創建一個分層對象。d3嵌套在幾個鍵與循環

請你幫我理解爲什麼下面的代碼不起作用。 我沒有設法在循環中使用嵌套函數,如下所述。

我有以下的CSV文件,從例子中的D3網站採取:

"type1","type2","type3","type4","type5","size" 
"flare","analytics","cluster","AgglomerativeCluster","","3938" 
"flare","analytics","cluster","CommunityStructure","","3812" 
"flare","analytics","cluster","MergeEdge","","743" 
"flare","analytics","graph","BetweennessCentrality","","3534" 
"flare","analytics","graph","LinkDistance","","5731" 

這個基本的嵌套的工作原理:

data = data.entries(csv) 
     .key(function(d) {return d.type1; }) 
     .key(function(d) {return d.type2; }) 
     .key(function(d) {return d.type3; }) 
     .entries(csv); 

我想用值的數組來指定我的鑰匙以便動態修改它們。

這工作:

var data = d3.nest(); 
    var nesting = ["type1","type2","type3"]; 
    data = data.key(function(d) {return d[nesting[0]]; }); 
    data = data.key(function(d) {return d[nesting[1]]; }); 
    data = data.key(function(d) {return d[nesting[2]]; }); 
    data = data.entries(csv); 

但它不與循環工作...

var data = d3.nest(); 
    for(var i=0;i<nesting.length;i++) 
    { 
     data = data.key(function(d) {return d[nesting[i]]; }); 
    } 
    data = data.entries(csv); 

我不明白爲什麼循環的版本是不工作...也許我錯過一些關於d3.nest()的功能......

另外,我想知道是否有一種方法可以「跳過」嵌套層次,如果在這個層次上沒有填充(即:「type5」在額外的所有線上ct以上)。我怎麼能這樣做?

非常感謝您的閱讀!

回答

13

這不是.nest()運算符的問題,這是JavaScript關閉的問題。任何時候你有這種模式:

for (var x=0; x < y; x++) { 
    something.attachCallback(function() { 
     // now do something with x 
    }); 
} 

你將有關閉問題。您定義的內部匿名函數不包含x值的副本,它包含參考至外部變量x,外部變量將在外部變量更新時更新。因此,在循環結束時,的值爲,每您的回調函數之一將是循環中x的最終值(在上面的代碼中,y;在您的代碼中,nesting.length)。

的D3 .nest()運營商使用其.key()參數爲回調 - 他們不執行,直到你打電話.map().entries()。所以上述問題適用。

有多種方法可以解決這個問題;我傾向於使用.forEach()而不是for循環。這並不在舊的瀏覽器,但也不會最D3的,所以你可能是安全的:

var data = d3.nest(); 
nesting.forEach(function(key) { 
    data.key(function(d) {return d[key]; }) 
}); 

另一種選擇是使用一個單獨的函數回調定義。經過迭代變量到另一個功能將「修正」它的價值,作爲回調現在有創建者函數的自變量,而不是原來的x變量的引用:

var data = d3.nest(); 

function addKey(index) { 
    data.key(function(d) { return d[nesting[index]]; }) 
} 

for(var i=0;i<nesting.length;i++) { 
    addKey(i); 
} 

還有一些其他的方法好吧,但在我看來forEach是最優雅的。

+0

喜規範的地方。非常感謝您的回答。現在非常清楚! – bobby

+0

@nrabinowitz @nabinowitz不應該把葉節點當作'key:something,values:number'來代替,當我們的葉節點(結尾的節點)有你的代碼時,它有'key:something,values:[]'!它有一個數組而不是數值!任何想法如何讓'價值'成爲數字? – Ciwan

+0

如果我需要根據組來確定級別,該怎麼辦?假設我有兩個關鍵組,而我應該如何知道這個關卡是基於這個值呢?不知何故,我可以添加attr,我用attkey等關鍵屬性組? –

1

遲到了,但是這是對@Ciwan上面評論#2的迴應。我沒有足夠的「信譽」發表評論,所以我來回答此:

d3.nest()結果是正確的:

{ key: something, values: [all,the,items,that,are,grouped,by,the,key] } 

如果你寧願有那些項目的計數,你可以使用d3.nest()的彙總,就像這樣:

var data = d3.nest().rollup(function(leaves) { return leaves.length; }) 

Phoebe Bright's bl.ock是瞭解d3.nest()