2017-01-28 15 views
0

Доброго вечера,dc.js Composite Graph - земля Новой линии для каждого человек

Я пытаюсь взять данные из базы данных, полных отчетов часов (имя, метки времени, количество отработанных часов и т.д.) и создайте график, используя dc.js для визуализации данных. Я хотел бы, чтобы временная метка находилась на оси x, сумме часов для конкретной отметки времени по оси y и новой гистограммы для каждого уникального имени на одной диаграмме.

Похоже на то, что с использованием crossfilter.js отметка времени должна быть моей «размерностью», а затем суммой часов должна быть моя «группа».

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

Вопрос 2, мои временные метки находятся в формате даты и времени MySQL: YYYY-mm-dd HH: MM: SS, так как бы я пошел о снижении точности? Например, если я хочу объединить все записи с одного дня в одну запись (точность дня) или объединить все записи за один месяц в одну запись (точность месяца).

Заранее благодарен!

---- Добавлено 2017/01/28 16:06

Для дальнейшего уточнения, я ссылки на API-интерфейсы Crossfilter & DC наряду с DC NASDAQ и Composite примеров. Пример Composite показал мне, как разместить несколько линейных/гистограмм на одном графике. На составной диаграмме, которую я создал, на каждой из гистограмм я добавил измерение, основанное на отметках времени в наборе данных. Теперь я пытаюсь выяснить, как определить группы для каждого. Я хочу, чтобы каждая гистограмма отображала общее время работы за метку времени.

Например, у меня есть пять человек в моей базе данных, поэтому я хочу, чтобы в одной составной диаграмме было пять диаграмм. Сегодня все пять представленных отчетов говорят, что они работали 8 часов, так что теперь все пять гистограмм должны показывать отметку на 28.08.2017 по оси x и 8 часов по оси y.

var parseDate = d3.time.format('%Y-%m-%d %H:%M:%S').parse; 
    data.forEach(function(d) { 
     d.timestamp = parseDate(d.timestamp); 
    }); 
    var ndx    = crossfilter(data); 
    var writtenDimension = ndx.dimension(function(d) { 
     return d.timestamp; 
    }); 
    var hoursSumGroup = writtenDimension.group().reduceSum(function(d) { 
     return d.time_total; 
    }); 
    var minDate = parseDate('2017-01-01 00:00:00'); 
    var maxDate = parseDate('2017-01-31 23:59:59'); 
    var mybarChart = dc.compositeChart("#my_chart"); 
    mybarChart 
     .width(window.innerWidth) 
     .height(480) 
     .x(d3.time.scale().domain([minDate,maxDate])) 
     .brushOn(false) 
     .clipPadding(10) 
     .yAxisLabel("This is the Y Axis!") 
     .compose([ 
     dc.barChart(mybarChart) 
      .dimension(writtenDimension) 
      .colors('red') 
      .group(hoursSumGroup, "Top Line") 
     ]); 

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

На данный момент я не знаю, как продолжить распад группы часовSumGroup на основе каждого человека, и именно здесь приходит мой вопрос №1, и мне нужна помощь в выяснении.

Вопрос № 2 выше, что я хочу убедиться, что код является динамическим (больше людей могут обрабатываться без изменения кода), когда minDate и maxDate позже привязаны к полям ввода пользователя, диаграммы обновляются автоматически (I предположите, что каким-то образом отрегулируйте переменную размера), и если я добавлю фильтр имен, если я отменим выбор имен, которые будет обновляться диаграммой, удалив данные для этого человека.

Вопрос №3, который я сейчас понимаю, я хочу выяснить, как получить имя человека в подсказке указателя (название) вместе с значениями timestamp и total_time.

+0

Привет, добро пожаловать в SO и dc.js! Я не уверен, что вы имеете в виду со всеми упоминаниями о барах - ищете ли вы [диаграмму линейных рядов] (http://dc-js.github.io/dc.js/examples/series.html)? Также обратите внимание на [пример временных интервалов переключения] (http://dc-js.github.io/dc.js/examples/switching-time-intervals.html) за идею объединить по дням или месяцам. Наконец, вот [документация для d3.time.format.parse] (https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#parse), для превращая ваши строки в объекты даты. – Gordon

+0

Поскольку это стоит, это не большой вопрос, лучше здесь прыгать и начинать кодирование и ждать, пока вы не застрянете, прежде чем обращаться за помощью. Если вы хотите провести более неторопливое обсуждение, не стесняйтесь связаться [в группе пользователей] (https://groups.google.com/forum/?fromgroups#!forum/dc-js-user-group). Я не оставил закрытого голоса, но я бы сказал, что он немного широк, поскольку он стоит. – Gordon

+0

Гордон, я обновил свой вопрос выше в ответ на ваши комментарии. Достаточно ли изменений, чтобы лучше понять, что я хочу делать? – engnfrc

ответ

0

Существует несколько способов сделать это, но я думаю, что проще всего создать индивидуальное сокращение, которое сводит каждого человека в под-бункер.

Во-первых, решение вопроса № 2, вы хотите, чтобы настроить размер на основе интервала времени вы заинтересованы в Например, если вы смотрите на дни:.

var writtenDimension = ndx.dimension(function(d) { 
    return d3.time.hour(d.timestamp); 
}); 
chart.xUnits(d3.time.hours); 

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

Далее, вот сокращение выборочного (from the FAQ), который создает объект для каждого восстановленного значения со значениями для имени каждого человека:

var hoursSumGroup = writtenDimension.group().reduce(
    function(p, v) { // add 
     p[v.name] = (p[v.name] || 0) + d.time_total; 
     return p; 
    }, 
    function(p, v) { // remove 
     p[v.name] -= d.time_total; 
     return p; 
    }, 
    function() { // init 
     return {}; 
    });  

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

Далее мы можем комбинировать составные линейные диаграммы с помощью атрибутов значений, которые могут извлекать значение по имени.

Предположим, у нас есть массив names.

compositeChart.shareTitle(false); 
compositeChart.compose(
    names.map(function(name) { 
     return dc.lineChart(compositeChart) 
      .dimension(writtenDimension) 
      .colors('red') 
      .group(hoursSumGroup) 
      .valueAccessor(function(kv) { 
       return kv.value[name]; 
      }) 
      .title(function(kv) { 
       return name + ' ' + kv.key + ': ' + kv.value; 
      }); 
    })); 

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

Если вы отфильтровываете имя в другом месте, это приведет к тому, что строка для названия упадет до нуля. Полное исчезновение линии, вероятно, будет не так просто.

Вышеуказанный shareTitle(false) гарантирует, что детские диаграммы будут рисовать собственные названия; функции title просто добавляют текущее имя к этим заголовкам (обычно это будет просто ключ: значение).

+0

Спасибо, Гордон, я сделал что-то очень похожее на это и прекрасно работает! – engnfrc