4

CSV ファイルから階層オブジェクトを作成するために d3.nest() を使用しています。

次のコードが機能しない理由を教えてください。以下で説明するように、ループ内でネスト関数を使用することができませんでした。

d3 Web サイトの例から取得した次の CSV ファイルがあります。

"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」レベル)。どうすればそれができますか?

読んでくれてありがとう!

4

2 に答える 2

16

これは.nest()オペレーターの問題ではなく、JavaScript クロージャーの問題です。このパターンがあるときはいつでも:

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

閉鎖に問題が発生します。定義している内部匿名関数には、 の値のコピーが含まれていません。外部変数が更新されると更新される外部変数 への参照xが含まれています。したがって、ループの終わりまでに、コールバック関数のすべての の値は、ループ内の の最終値になります (上記のコードでは; コードでは)。xxxynesting.length

D3.nest()オペレーターはその引数をコールバックとして使用します。それらは、 または.key()を呼び出すまで実行されません。したがって、上記の問題が適用されます。.map().entries()

これを修正するにはさまざまな方法があります。ループ.forEach()の代わりに使用する傾向があります。forこれは古いブラウザーでは機能しませんが、ほとんどの D3 では機能しないため、おそらく安全です。

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

もう 1 つのオプションは、コールバック定義に別の関数を使用することです。反復子変数を別の関数に渡すと、その値が「修正」されます。これは、コールバックが元の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では最もエレガントです。

于 2012-09-14T00:38:58.607 に答える
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 の bl.ockは、d3.nest() について学ぶための正規の場所です。

于 2016-01-15T07:10:47.907 に答える