2014-12-07 1 views
1

У меня есть набор данных CSV, который я использую с dc.js (crossfilter).Уменьшить несколько косвенно заданных полей с использованием crossfilter

Date, Country 1,Country 2,Country 3,Country 4,Country 5,Country 6,Target country (...) 2014/12/11, USA, France, UAE, (...), Iraq

То, что я пытаюсь сделать, это для построения строки диаграммы с один ряд в стране. Вот мое решение, как сегодня:

var countries = ndx.dimension(function(d) { 
    var list = []; 
    list.push(d["Country 1"]); 
    if (d["Country 2"]) {list.push(d["Country 2"]);}; 
    if (d["Country 3"]) {list.push(d["Country 3"]);}; 
    if (d["Country 4"]) {list.push(d["Country 4"]);}; 
    if (d["Country 5"]) {list.push(d["Country 5"]);}; 
    if (d["Country 6"]) {list.push(d["Country 6"]);}; 
    return list; 
    }); 
    var countriesGroup = countries.group().reduceSum(function(d) { 
    return d.totalNumberOfStrikes; 
    });; 
    countryChart 
    .width(400).height(500) 
    .group(countriesGroup) 
    .dimension(countries) 
    .ordering(function(d){ return -d.value }); 

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

Что я хочу - это иметь список, содержащий каждую уникальную страну, а затем нарисовать объект в таблице строк.

Вы можете помочь? Большое спасибо!

ответ

1

на основе последующего разговора in another question и dc.js users group, вот лучшее сокращение, что хранит данные, как это:

var strikingCountriesGroup = xScaleDimension.group().reduce(
    function(p, v) { // add 
     countryFields.forEach(function(c) { 
      if(v[c]) p[v[c]] = (p[v[c]] || 0) + v.totalNumberOfStrikes; 
     }); 
     return p; 
    }, 
    function(p, v) { // remove 
     countryFields.forEach(function(c) { 
      if(v[c]) p[v[c]] = p[v[c]] - v.totalNumberOfStrikes; 
     }); 
     return p; 
    }, 
    function() { // initial 
     return {}; 
    } 
); 

Хотя это может выглядеть как большой клубок скобок, идея состоит в том, что поля v[c] , где c - это «Страна 1», «Страна 2» ... в исходном наборе данных косвенно укажите поля, которые вы хотите создать в сокращении.

Мы уменьшаем на карте p от значения v. Мы перебираем поля страны и для каждого c, если v имеет запись для c, добавим или вычтем v.totalNumberOfStrikes от p[v[c]]. Мы должны быть осторожны, если значение еще не существует: выражение || 0 присваивает значение нулю, если оно не определено.

Затем мы можем создать стеки динамически, как это (сортировка по значению):

var reducedCountries = strikingCountriesGroup.all()[0].value; 
    var countries = d3.keys(reducedCountries).sort(function(a, b) { 
     return reducedCountries[b] - reducedCountries[a]; 
    }); 

    // we have to special-case the first group, see https://github.com/dc-js/dc.js/issues/797 
    var first = countries.shift(); 
    strikingCountries 
     .group(strikingCountriesGroup, first, 
     function(d) { 
      return d.value[first]; 
     }); 
    // rest 
    countries.forEach(function(c) {  
     strikingCountries 
      .stack(strikingCountriesGroup, c, 
      function(d) { 
       return d.value[c]; 
      }); 
    }); 

Fiddle здесь: http://jsfiddle.net/gordonwoodhull/gfe04je9/11/

1

Возможно, самый простой способ сделать это - сгладить ваш массив, поэтому у вас есть только Date, Country, Target в вашем источнике. Что-то вроде (непроверенные):

var dest = []; 
var countries = ["Country 1", "Country 2", ...] 
source.forEach(function(d) { 
    countries.forEach(function(c) { 
     dest.push({Date: d.Date, Country: c, Target: d.Target}); 
    }); 
}); 

А затем передать dest в crossfilter вместо ваших исходных данных.

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

+0

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

+0

А, это хороший момент. Вы думаете об уменьшении объекта с полями для каждой страны? – Gordon

+0

Я так потерян, если честно.Прошу прощения со вчерашнего дня, без каких-либо успехов :( – basbabybel