2012-05-09 24 views
14

Al usar Crossfilter (https://github.com/square/crossfilter), especifico funciones para usar al agregar y eliminar datos de un grupo. Es bastante trivial para realizar un seguimiento de un promedio de ejecución (utilizando CoffeeScript):Usando Crossfilter, ¿es posible rastrear max/min cuando se agrupa?

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 
    } 

¿Es posible hacer un seguimiento de la máxima y mínima de cada grupo? No puedo encontrar una manera de mantener todos los elementos en una gran variedad y hacer un d3.min/d3.max. Parece que agregar/eliminar datos sería extremadamente ineficiente.

También buscó una manera de contar Crossfilter para reconstruir por completo el grupo a partir de cero, en lugar de la eliminación de elementos de un grupo existente. Si se aplica un filtro, el grupo se restablece y reconstruye. Nada obvio.

+0

acaba de ejecutar en el mismo problema. Por cierto, he abierto un problema en GitHub, https://github.com/square/crossfilter/issues/25 – CambridgeMike

Respuesta

0

Después de jugar con esto por un poco, puede reconstruir el grupo con sólo llamar al método de grupo de nuevo.

+0

Interesante, lo comprobaré out.BTW, no pude hacer una etiqueta 'crossfilter' en SO sin más reputación. Si alguien se topa con esto y puede crear una etiqueta, me complace volver a etiquetar mi pregunta. –

+1

Acabo de crear la etiqueta. Crossfilter es una gran biblioteca con la esperanza de que reciba más atención. – Pablojim

+1

¿Puede explicar la solución con más detalle? ¿Cuándo/cómo reconstruyes el grupo? –

9

Puede usar dimension.top(1) y dimension.bottom(1) para recuperar la corriente mínima y máxima. Estos métodos respetan cualquier filtro que pueda estar activo en el filtro cruzado.

+1

¿Cómo usaría dimension.top y dimension.bottom para obtener el máximo y mínimo por grupo? –

2

La mejor solución que se me ocurrió, fue hacer un seguimiento de todos los valores en una lista ordenada y agregar elementos con una función de inserción de estilo quicksort simple (cp. Cómo insert a number into a sorted array) y eliminarlos usando indexOf.

funciones comunes:

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

funciones que utilizará cuando adición y eliminación de datos de un grupo para realizar un seguimiento min/max:

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

esta es la solución más eficiente de lejos. – Gordon

+0

Creo que puede usar [d3.bisectRight] (https://github.com/mbostock/d3/wiki/Arrays#d3_bisectRight) en lugar de 'locationOfElement' – Gordon

Cuestiones relacionadas