2012-05-09 9 views
14

CrossFilter(https://github.com/square/crossfilter)を使用する場合、グループにデータを追加したり削除したりするときに使用する関数を指定します。これは、(CoffeeScriptのを使用して)移動平均を追跡するために、かなり些細です:Crossfilterを使用すると、グループ化するときに最大/最小を追跡できますか?

reduceAdd = (p, v) -> 
    ++p.count; 
    p.sum += v.digit; 
    p 

reduceRemove = (p, v) -> 
    --p.count; 
    p.sum -= v.digit; 
    p 

reduceInitial = -> 
    { 
    count: 0 
    sum: 0 
    average: -> 
     return 0 if this.count == 0 
     return this.sum/this.count 
    } 

は、各グループの最大と最小を追跡することが可能ですか?私は巨大な配列のすべての要素を保持し、d3.min/d3.maxを実行する方法が不足していることを理解できません。データの追加/削除は非常に効率的ではないようです。

また、既存のグループからアイテムを削除するのではなく、最初からグループを完全に再構築するようにCrossfilterに指示する方法を探しました。フィルタが適用されると、グループはリセットされ、再構築されます。何も明らかではない。

+0

はちょうど同じ問題に遭遇しました。 BTW、githubで問題を開けました、https://github.com/square/crossfilter/issues/25 – CambridgeMike

答えて

0

これでやりなおした後、もう一度groupメソッドを呼び出すだけで、グループを再構築できます。

+0

興味深い、私はそれをチェックします.BTW、私はそれ以上のことなしで 'crossfilter'タグを作ることができませんでした評判。誰かがこれに遭遇してタグを作成できる場合は、私の質問にタグを付け直すことができます。 –

+1

タグを作成しました。 Crossfilterはうまくいけば大きなライブラリです。 – Pablojim

+1

解決策をより詳しく説明できますか?あなたはどのようにグループを再構築しますか? –

9

dimension.top(1)dimension.bottom(1)を使用すると、現在の最小値と最大値を取得できます。これらのメソッドは、クロスフィルタでアクティブなフィルタを対象としています。

+1

dimension.topとdimension.bottomを使用してグループごとに最大値と最小値を取得するにはどうすればよいですか? –

2

私が思いついた最善の解決策は、順序付きリストのすべての値を追跡し、単純なクイックソートスタイルの挿入関数(cp。how to insert a number into a sorted array)で要素を追加し、indexOfを使用してそれらを削除することでした。

共通機能:

function insertElement(element, array) { 
    array.splice(locationOfElement(element, array) + 1, 0, element); 
    return array; 
} 

function removeElement(element, array) { 
    var index = array.indexOf(element); 
    if (index >= 0) array.splice(index, 1); 
    return array; 
} 

function locationOfElement(element, array, start, end) { 
    start = start || 0; 
    end = end || array.length; 
    var pivot = parseInt(start + (end - start)/2, 10); 
    if (array[pivot] === element) return pivot; 
    if (end - start <= 1) 
     return array[pivot] > element ? pivot - 1 : pivot; 
    if (array[pivot] < element) { 
     return locationOfElement(element, array, pivot, end); 
    } else { 
     return locationOfElement(element, array, start, pivot); 
    } 
} 

function maxElement(array) { 
    return (array.length > 0) ? 
     array[array.length - 1] : null; 
} 

function minElement(array) { 
    return (array.length > 0) ? 
     array[0] : null; 
} 

機能最小/最大を追跡するために、グループからの追加と削除データを使用する:

minMaxDimension = cf.dimension(function (d) { 
    return d.key; 
}); 

var reduceAdd = function(p, v) { 
    insertElement(v.value, p.elements); 
    return p; 
}; 

var reduceRemove = function(p, v) { 
    removeElement(v.value, p.elements); 
    return p; 
}; 

var reduceInitial = function() { 
    return { 
     elements: [], 
     max: function() { return maxElement(elements); }, 
     min: function() { return minElement(elements); } 
    } 
} 

minMaxGroup = minMaxDimension 
    .group() 
    .reduce(reduceAdd, reduceRemove, reduceInitial) 
    .orderNatural() 
    .top(Infinity); 
+0

これははるかに効率的な解決策です。 – Gordon

+0

あなたは 'locationOfElement'の代わりに[d3.bisectRight](https://github.com/mbostock/d3/wiki/Arrays#d3_bisectRight)を使うことができると思います – Gordon

関連する問題