2015-04-12 2 views
8

У меня есть группа графиков, визуализирующая кучу данных для меня (here), основанная на csv с примерно 25 000 строк данных, каждая из которых имеет 12 параметров. Однако любое взаимодействие (например, выбор диапазона с помощью кисти на любом из графиков) является медленным и громоздким, полностью отличным от the dc.js demo found here, которое также относится к тысячам записей, но поддерживает плавные анимации или crossfilter's demo here, что в 10 раз больше записи (полеты), как и я.Оптимизация группы линейных графиков dc.js

Я знаю, что основные ресурсные свиньи - это две линейные диаграммы, так как они имеют точки данных каждые 15 минут в течение примерно 8 твердых месяцев. Удаление одного из них заставляет диаграммы реагировать снова, но они являются главной особенностью визуализации, так что я могу сделать их менее мелкозернистыми данными?

Код для двух линейных графиков конкретно ниже:

 var lineZoomGraph = dc.lineChart("#chart-line-zoom") 
      .width(1100) 
      .height(60) 
      .margins({top: 0, right: 50, bottom: 20, left: 40}) 
      .dimension(dateDim) 
      .group(tempGroup) 
      .x(d3.time.scale().domain([minDate,maxDate])); 

     var tempLineGraph = dc.lineChart("#chart-line-tempPer15Min") 
      .width(1100).height(240) 
      .dimension(dateDim) 
      .group(tempGroup) 
      .mouseZoomable(true) 
      .rangeChart(lineZoomGraph) 
      .brushOn(false) 
      .x(d3.time.scale().domain([minDate,maxDate])); 

Раздельное но уместный вопрос; как изменить ось y на линейных диаграммах? По умолчанию они не охватывают самые высокие и самые низкие значения, найденные в наборе данных, что кажется странным.

Edit: некоторый код, который я написал, чтобы попытаться решить эту проблему:

var graphWidth = 1100; 
var dataPerPixel = data.length/graphWidth; 

var tempGroup = dateDim.group().reduceSum(function(d) { 
    if (d.pointNumber % Math.ceil(dataPerPixel) === 0) { 
     return d.warmth; 
    } 
}); 

d.pointNumber единственной точка ID для каждой точки данных, накопленной от 0 до 22000 иша. Теперь, однако, линейный график отображается пустым. Я проверил данные группы с помощью tempGroup.all(), и теперь каждая 21-я точка данных имеет значение температуры, но все остальные имеют NaN. Мне вообще не удалось уменьшить размер группы; он все еще составляет 22 тысячи или около того. Интересно, правильно ли это ...

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

var tempGroup = dateDim.group().reduceSum(function(d) { return d.warmth; }); 
    var filteredTempGroup = { 
     all: function() { 
      return tempGroup.top(Infinity).filter(function (d) { 
       if (d.pointNumber % Math.ceil(dataPerPixel) === 0) return d.value; 
      }); 
     } 
    }; 

У меня проблема в том, что d.pointNumber не доступен, так что я не могу сказать, если это Nth точка данных (или кратна этого). Если я назначу его var, это будет как раз фиксированное значение, так что я не уверен, как обойти это ...

+1

«подделка группа "в вашем втором редактировании кажется разумным. Так как ваши данные, вероятно, находятся в порядке дат в любом случае (?), индекс должен быть примерно таким же, как «pointNumber», поэтому добавление параметра в функцию обратного вызова фильтра должно дать вам индекс, который вы можете использовать: '.filter (function (d, i) {return (i% Math .ceil (dataPerPixel) === 0);}) '. Также обратите внимание, что функция обратного вызова фильтра должна возвращать значение boolean, а не значение. – Gordon

+0

ОК, так что работает, вроде. Я получаю гораздо более управляемые результаты 1071, но результаты тоже не в порядке, что меня смущает. Если вы посмотрите на веб-сайт в прямом эфире, вы поймете, что я имею в виду. Объекты группы начинаются правильно в первых нескольких точках данных, затем перепрыгивают через несколько дней, а затем отскакивают назад ... так что точки в порядке, просто как-то беспорядочно. – IronWaffleMan

+1

Ум, да, вы, вероятно, хотите использовать '.all()' вместо '.top (Infinity)', по понятным причинам. Пропустил это. – Gordon

ответ

4

При работе с проблемами производительности с диаграммами на основе d3 обычным виновником является количество элементов DOM, а не размер данных. Обратите внимание, что демоверсия crossfilter содержит множество строк данных, но всего пару сотен баров.

Похоже, что вы пытаетесь построить все точки вместо их объединения. Я предполагаю, что, поскольку вы делаете временные ряды, может быть неинтересно объединять точки, но считайте, что ваш сюжет может отображать только 1100 точек (ширина), поэтому бессмысленно перегружать двигатель SVG, отображая 25 000.

Я предлагаю снести его где-то между 100-1000 ящиками, например. путем усреднения каждый день:

var daysDim = data.dimension(function(d) { return d3.time.day(d.time); }); 

function reduceAddAvg(attr) { 
    return function(p,v) { 
    if (_.isLegitNumber(v[attr])) { 
     ++p.count 
     p.sums += v[attr]; 
     p.averages = (p.count === 0) ? 0 : p.sums/p.count; // gaurd against dividing by zero 
    } 
    return p; 
    }; 
} 
function reduceRemoveAvg(attr) { 
    return function(p,v) { 
    if (_.isLegitNumber(v[attr])) { 
     --p.count 
     p.sums -= v[attr]; 
     p.averages = (p.count === 0) ? 0 : p.sums/p.count; 
    } 
    return p; 
    }; 
} 
function reduceInitAvg() { 
    return {count:0, sums:0, averages:0}; 
} 
... 
// average a parameter (column) named "param" 
var daysGroup = dim.group().reduce(reduceAddAvg('param'), reduceRemoveAvg('param'), reduceInitAvg); 

(многоразовые среднем уменьшить ФУНКЦИИ from the FAQ)

Затем укажите свой xUnits, чтобы соответствовать, и использовать elasticY для автоматического расчета оси Y:

chart.xUnits(d3.time.days) 
    .elasticY(true) 
+0

Спасибо за предложение ... Я отправился на поиски других людей, использующих функции повторной выборки на линейных графиках в d3, но нет конкретных примеров, которые я нахожу странными, поскольку у кого-то была проблема в какой-то момент ... Я попытался решить ее самостоятельно с помощью функции, которую я ввел в редактирование в своем первоначальном ответе, но проблема в том, что она не избавляется от исходных данных, только делает каждую точку данных N имеющей значение, а остальное NaN. – IronWaffleMan

+0

Вы использовали функции сокращения, предложенные Гордоном? – Xavier

+0

Сэмплинг - это метод данных, а не техника построения диаграмм, если это поможет вашему поиску. Ваша попытка выглядела в основном для меня, но я не пробовал. Лично я придерживаюсь средних значений, чтобы не потерять данные, так как этот объем данных должен быть хорошим в JavaScript – Gordon