2014-03-05 1 views
0

Новый перекрестный фильтр. Я плоский данные, которые приведены ниже:Как сделать group.reduce в плоских данных в crossfilter

id,name,patientId,conditionId,isPrimary,age,gender,race,Status,CGI 
1,M1,1,c1,Y,33,Male,White,Discharged,0 
2,M2,1,c1,N,33,Male,White,Discharged,0 
3,M3,1,c2,N,33,Male,White,Discharged,0 
4,M4,1,c2,N,33,Male,White,Discharged,0 
5,M5,1,c3,N,33,Male,White,Discharged,0 
6,M6,1,c3,N,33,Male,White,Discharged,0 
25,M1,5,c1,Y,33,Male,White,Discharged,1 
26,M7,5,c2,N,33,Male,White,Discharged,1 
27,M4,5,c4,N,33,Male,White,Discharged,1 
28,M4,5,c1,N,33,Male,White,Discharged,1 
29,M4,5,c2,N,33,Male,White,Discharged,1 
30,M5,5,c4,N,33,Male,White,Discharged,1 
29,M2,6,c1,Y,33,Male,White,Discharged,1 
30,M2,7,c1,Y,33,Male,White,Discharged,1 

Я хочу сделать подсчет на conditionId, но так как есть несколько записей, принадлежащих одному и тому же лицу, идентифицированная patientId, подсчет стоимости c1 должен быть 4 (принадлежащий patientId 1, 5, 6, 7) - потому что у одного пациента может быть несколько записей (например, patientId из 1 повторяется 6 раз, а два из них имеют c1, который следует учитывать только один раз). Я изо всех сил пытаюсь написать group.reduce на conditionId, но не мог даже начать.

Заранее спасибо.

+0

Каков ваш желаемый результат? Вам просто нужен счетчик для c1 или вам нужна карта со счетами для каждого условия? – plalx

+0

Мне нужен счет conditionId, который должен быть c1: 4, c2: 2, c3: 1 и c4: 1. Спасибо. – user203617

ответ

0

Вот один из способов сделать это. В примере я предположил, что первым значением было patientId, а второе значение - conditionId. Код отслеживает группировку клавиш (объединение patientId и conditionId), которые уже были замечены и игнорируют их.

var countMap = [ 
    [1, 'c1'], 
    [1, 'c1'], 
    [2, 'c1'], 
    [2, 'c2'] 
].reduce(function (r, v) { 
    var condition = v[1], 
     groupKey = v[0] + condition; 

    if (!r.seen[groupKey]) { 
     r.seen[groupKey] = true; 
     r.count[condition] = (r.count[condition] || 0) + 1; 
    } 

    return r; 

}, {seen: {}, count: {}}).count; 


countMap.c1; //2 
countMap.c2; //1 

Я не знаю о crossfilter или dc.js, вот почему я дал вам решение Vanilla JS.

0

Это немного сложно сделать это в Crossfilter, но решение аналогично решению, предоставленному @plalx.

Это вспомогательная функция, которую я использую в одном из моих проектов. Это не идеально, и немного оптимизирован для сокращения поиска в словарях, поэтому он не самый читаемый. Основная идея заключается в том, что вам необходимо сохранить словарь значений, который был ранее рассмотрен для каждой группы. Вам только нужно помнить пациентов, так как условие уже известно, на основе группы ваш находятся в:

function reduceHelper(accessorFunction) { 
     var internalCount; 
     return { 
      add: function (p, v) { 
       if(p.unique.has(accessorFunction(v))) { 
        internalCount = p.unique.get(accessorFunction(v)); 
        p.unique.set(accessorFunction(v), internalCount + 1); 
       } else { 
        p.unique.set(accessorFunction(v), 1); 
        ++p.count; 
       } 
       return p; 
      }, 
      remove: function (p, v) { 
       if(p.unique.has(accessorFunction(v))) { 
        internalCount = p.unique.get(accessorFunction(v)); 
        if(internalCount == 1) { 
         p.unique.remove(accessorFunction(v)); 
         --p.count; 
        } else { 
         p.unique.set(accessorFunction(v), internalCount - 1); 
        } 
       } 
       return p; 
      }, 
      init: function() { 
       return {unique: d3.map(), count: 0}; 
      } 
     }; 
    } 

Вам нужно создать Crossfilter (xfilter) на ваших данных, а затем:

var helperFunctions = reduceHelper(function(d) { return d.patientId; }); 
var dim = xfilter.dimension(function (d) { return d.conditionId; }; 
var group = dim.group() 
       .reduce(helperFunctions.add, helperFunctions.remove, helperFunctions.init); 

Ваша группа теперь будет подсчитывать количество пациентов, у которых есть все условия. Если для данного пациента более одного раза появляется условие, этот пациент будет считаться только один раз. По крайней мере, это будет, если мое решение работает правильно :-)

+0

Thanx! Ты гений! :) – user203617