2014-12-21 5 views
0

У меня возникли проблемы с группированием выборок на основе вычислений, выполненных против значения одного поля. Образцы в формеГруппировка образцов на основе значения, зависящего от одного поля

{ 
 
    "dataset": "DATASET2", 
 
    "sampleid": "ID2653", 
 
    "variables": { 
 
    // several variables, key: val 
 
    }, 
 
    "bmus": { 
 
    "x": 3, 
 
    "y": 7 
 
    } 
 
}

Образцы принадлежат к клетке в статическом 9x7 сетке и ОМА поле отображает местоположение образца в сетке. Круговые фильтры можно перемещать поверх сетки, а после перемещения круглых фильтров я хочу иметь возможность группировать образцы, расположенные внутри круга. Группировка была бы в виде

{ 
 
    "key": { 
 
    "circles": ["circle1", "circle2"] // or [], ['circle1'], ['circle2'] 
 
    }, 
 
    "value": 282 
 
}

и после этого пользовательского снижения функции будет применяться для вычисления значений на основе значений некоторых переменных.

Моя текущая настройка для создания измерения и группировки заключается в следующем:

$scope.dimension = crossfilterInst.dimension(function(d) { 
 
    return { 
 
    bmu: d.bmus, 
 
    valueOf: function() { 
 
     var ret = _.isUndefined(d.bmus) ? String(constants.nanValue) + "|" + String(constants.nanValue) : d.bmus.x + "|" + d.bmus.y; 
 
     // for NaN's the result is "-100|-100", otherwise in the form of "5|4" 
 
     return ret; 
 
    } 
 
    }; 
 
}); 
 

 
var group = $scope.dimension.group(function(d) { 
 
    return { 
 
     circles: function() { 
 
     return FilterService.inWhatCircles(d.bmu); 
 
     }, 
 
     valueOf: function() { 
 
     return String(this.circles()); 
 
     } 
 
    }; 
 
});

Во-первых, группировки group.all() являются правильными. Позже, когда круговые фильтры перемещаются по сетке, тем самым воздействуя на выбранное количество образцов, применяя filterFunction к другому измерению crossfilterInst и тем самым влияя на возвращаемое значение от FilterService.inWhatCircles(), группы, возвращаемые с group.all(), имеют все более и более неправильные отсчеты образцов.

Первоначально я думал, что возвращаемое значение FilterService.inWhatCircles() было бы неправильным в некоторых случаях. После долгого отладки я заметил, что если я заново создаю измерение (поставлю старый + запустите тот же код, который создает $scope.dimension), а затем используйте тот же код для группировки образцов, результирующие группы верны.

Глядя на Crossfilter API, я подозреваю, что crossfilter делает некоторое кэширование, что щурит мою группировку, или что это требование не выполнено:

Подобно функциям значения, groupValue должен возвращать естественно упорядоченную значения; кроме того, этот порядок должен соответствовать функции значения .

Короче: как я могу вычислить FilterService.inWhatCircles() на основе bmus области образцов и сгруппировать их вместе повторно, когда функция возвращает значение может измениться, без необходимости воссоздать измерение каждый раз, чтобы получить правильные группы?

ответ

1

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

Тот факт, что ваши групповые ключи не соответствуют вашим размерным клавишам, является наименьшей из ваших проблем.

Вместо этого, вы можете использовать fake group, объект с .all() методом, который перебирает все точки данных и подсчитывает количество, которые соответствуют каждому inWhatCircles значения, например, используя карту. Затем он должен возвращать тот же самый массив пар {ключ, значение}, который возвращает group.all.

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

+0

Хорошо, так что кажется, что метод, к которому я стремился, невозможен или, по крайней мере, возможен с чистым перекрестным фильтром. Я понимаю, что инициализация измерения снова и снова не вариант, но подумал бы, что повторного формирования группировки было бы достаточно. Я фактически использовал метод поддельной группы, чтобы обойти мою проблему (группируя на основе '' d.bmu'', а затем объединяя группы, чтобы получить то, что мне нужно). Это субоптимально для моих потребностей, потому что пользовательские функции сокращения функции должны быть объединены. Но я думаю, что crossfilter специально не предназначен для использования для такого динамического расчета. – amergin

+0

Все проектные решения в crossfilter - это эффективность. Здесь легко пересчитать сокращения, но сложно (вычислительно) перемещать строки между группами. Поддельное групповое решение, о котором я говорю, должно быть таким же эффективным, как и все. – Gordon