2015-04-08 2 views
1

Я пытаюсь создать средневзвешенное значение, основанное на двух разных измерениях в CrossFilter. Есть ли способ написать пользовательские функции сокращения для этого? У меня есть:Взвешенная средняя функция уменьшения в CrossFilter

function reduceAddAvg(attr) { 
    return function(p,v) { 
    ++p.count 
    p.sum += v[attr]; 
     if (p.count == 0) {   //so we don't divide by zero 
      p.avg = 0; 
     }else { 
      p.avg = p.sum/p.count; 
     }  
    return p; 
    } 
} 
function reduceRemoveAvg(attr) { 
    return function(p,v) {  
    --p.count 
    p.sum -= v[attr]; 
     if (p.count == 0) { 
      p.avg = 0; 
     }else { 
      p.avg = p.sum/p.count; 
     }  
    return p; 
    } 
} 
function reduceInitAvg() { 

    return {count:0, sum:0, avg:0}; 
}    

и

var rent = ndx.dimension(function(d){ 
    return d.rent 
}) 
var units = ndx.dimension(function (d){ 
    return d.units 
}) 
var hood = ndx.dimension(function (d) { 
    return d.hood; 
}); 

мои данные выглядят следующим образом:

records = [{"hood":"SF","rent":"1000","units":"4"}, 
      {"hood":"NYC","rent":"1200","units":"5"}, 
      {"hood":"SF","rent":"1400","units":"8"}, 
      ] 

Я хочу вернуть арендную плату, взвешенную единицами (аренда * единиц)/единицы, так что результаты были бы быть таким:

{"key":"SF","value": (1000 * 4 + 1400 * 8)/(4+8)} 
    {"key":"NY,"value": 1200} 

Does Cross фильтр поддерживает это? Как я могу написать специальные функции сокращения для реализации этого?

+0

Да, это возможно - просто попробуйте. В вашей функции сокращения вычислите числитель и знаменатель так же, как вы в настоящее время вычисляете p.sum, а затем вычислите средневзвешенное значение, как вы в настоящее время вычисляете p.avg. –

ответ

1

Это то, что вы ищете ...

records = [{"hood":"SF","rent":1000,"units":4}, 
     {"hood":"NYC","rent":1200,"units":5}, 
     {"hood":"SF","rent":1400,"units":8}]; 

var ndx = crossfilter(records); 
var hoodDim = ndx.dimension(function (d) { 
return d.hood; 
}); 
var hoodGroup = hoodDim.group().reduce(
function reduceAdd(p, v) { 
    p.sumOfProds += (v.rent * v.units); 
    console.log("sumOfProds", p.sumOfProds); 
    p.unitsSum += v.units; 
    console.log("unitsSum", p.unitsSum); 
    p.finalVal = p.sumOfProds/p.unitsSum; 
    return p; 
}, 
function reduceRemove(p, v) { 
    p.sumOfProds -= (v.rent * v.units); 
    p.unitsSum -= v.units; 
    p.finalVal = p.unitsSum ? p.sumOfProds/p.unitsSum : 0; 
    return p; 
}, 
function reduceInitial() { 
    return { sumOfProds:0, unitsSum:0, finalVal:0 }; 
              }); 
hoodGroup.top(Infinity).forEach(function(d){ console.log(d.key, d.value.finalVal); }); 

Вот JSFiddle при необходимости.

Смежные вопросы