2016-07-13 2 views
2

Привет, мои друзья StackOverflow:Временные ряды анализа данных с использованием D3.js

Пришло время обратиться за помощью. Я несколько недель изучаю D3.js, и я начинаю чувствовать, что понимаю 10% (га, га, га). Я пытаюсь создать очень простой линейный граф. Я могу сделать это до тех пор, пока данные очень просты, но мой исходный источник данных имеет отметки времени UTC и реальные/десятичные числа, которые продолжают сбивать что-либо сверх простого.

Сырьевой источник данных выглядит следующим образом:

 

    { 
     "Links": {}, 
     "Items": [ 
     { 
      "Timestamp": "2016-07-12T22:21:10Z", 
      "Value": 1055.6793212890625, 
      "UnitsAbbreviation": "m3/h", 
      "Good": true, 
      "Questionable": false, 
      "Substituted": false 
     }, 
     { 
      "Timestamp": "2016-07-12T22:39:10Z", 
      "Value": 989.00830078125, 
      "UnitsAbbreviation": "m3/h", 
      "Good": true, 
      "Questionable": false, 
      "Substituted": false 
     } 
     ], 
     "UnitsAbbreviation": "m3/h" 
    } 

Использование JQuery и функции Javascript время форматирования Я могу собрать следующий упрощенный набор данных:

 

    var dataset = [ 
    {'theTime': '2016/07/12 15:58:40', 'theValue': 1123.07275390625}, 
    {'theTime': '2016/07/12 16:21:10', 'theValue': 1055.6793212890625}, 
    {'theTime': '2016/07/12 16:45:40', 'theValue': 962.4850463867188}, 
    {'theTime': '2016/07/12 17:14:40', 'theValue': 831.2259521484375}, 
    {'theTime': '2016/07/12 17:55:10', 'theValue': 625.3046875} 
    ]; 

Вот мой код:

 

    //~ Populate the 'dataset': 
    var dataset = []; 
    $.get(url, function(data){ 
     var itemCount = data.Items.length; 
     var commaCount = itemCount - 1; 
     for(i=0; i < itemCount; i++){ 
      if(i == commaCount){ 
       dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "}"); 
      } 
      else { 
      dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "},"); 
     } 
     } 

     var margin = {top: 20, right: 20, bottom: 30, left: 50}; 
     var width = 960 - margin.left - margin.right; 
     var height = 500 - margin.top - margin.bottom; 
     var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse; 
     var x = d3.time.scale() 
      .range([0, width]); 

     var y = d3.scale.linear() 
      .range([height, 0]); 

     var xAxis = d3.svg.axis() 
      .scale(x) 
      .orient("bottom"); 

     var yAxis = d3.svg.axis() 
      .scale(y) 
      .orient("left"); 

     var line = d3.svg.line() 
      .x(function(d) { return x(d.theTime); }) 
      .y(function(d) { return y(d.theValue); });  

     var svg = d3.select("#myChart").append("svg") 
      .attr("width", width + margin.left + margin.right) 
      .attr("height", height + margin.top + margin.bottom) 
      .append("g") 
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

      dataset.forEach(function(d) { 
       d.theTime = parseDate(d.theTime); 
       d.theValue = +d.theValue; 
      }); 

      x.domain(d3.extent(data, function(d) { return d.theTime; })); 
      y.domain(d3.extent(data, function(d) { return d.theValue;})); 

      svg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + height + ")") 
       .call(xAxis); 

      svg.append("g") 
       .attr("class", "y axis") 
       .call(yAxis) 
       .append("text") 
       .attr("transform", "rotate(-90)") 
       .attr("y", 6) 
       .attr("dy", ".71em") 
       .style("text-anchor", "end") 
       .text("return time(ms)"); 

      svg.append("path") 
       .datum(dataset) 
       .attr("class", "line") 
       .attr("d", line); 
     }); 

     //~~~ Format The Date: 
     function formattedDateTime(dateAndTime) { 
      var d = new Date(dateAndTime); 
      var numDate = d.getDate(); 
      var numMonth = d.getMonth() + 1; 
      var numYear = d.getFullYear(); 
      var numHours = d.getHours(); 
      var numMinutes = d.getMinutes(); 
      var numSeconds = d.getSeconds(); 
      numDate = (numDate < 10) ? "0" + numDate : numDate; 
      numMonth = (numMonth < 10) ? "0" + numMonth : numMonth; 
      numHours = (numHours < 10) ? "0" + numHours : numHours; 
      numMinutes = (numMinutes < 10) ? "0" + numMinutes : numMinutes; 
      numSeconds = (numSeconds < 10) ? "0" + numSeconds : numSeconds; 

      return numYear + "/" + numMonth + "/" + numDate + " " + 
     numHours + ":" + numMinutes + ":" + numSeconds; 
     }; 

Первая ошибка возникает в функции 'dataset.forEach()', wh ich «Uncaught TypeError: Cannot read property 'length' of undefined». Мое усилие там, чтобы проанализировать эти данные, проистекает из другой ошибки, которая возникает в точке «svg.append (« путь ») в коде, которая равна« Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL… ».

Uggghhhh! (: -C). Если в аудитории есть любые наставники D3.js, пожалуйста, помогите мне определить, что я делаю неправильно, и как это исправить. Большое спасибо!

// ============= прилагаемая 01 ========================

I это работало! Yeee Haaaw!

Опубликуйте пересмотренный рабочий код ниже. Но для тех, кто следил за этим сообщением, я хотел объяснить, что я нашел.

Марк в связанном сообщении (Alternatives for using forEeach() loop while converting data for D3.js) предложил изменить dataset.push(), чтобы удалить все кавычки. Это дало мне объекты вместо строк. После некоторого устранения неполадок он, наконец, выглядел так, как ожидалось (полностью псих!), И спасибо Марку, ваши предложения сделали трюк.

Вот пересмотренный код:

 

    //~ Populate the 'dataset': 
    var dataset = []; 
    $.get(url, function(data){ 
     var itemCount = data.Items.length; 
     var commaCount = itemCount - 1; 
     for(i=0; i<itemCount; i++){ 
      dataset.push({theTime: formattedDateTime(data.Items[i].Timestamp), theValue: data.Items[i].Value}); 
     } 

     var margin = {top: 20, right: 20, bottom: 30, left: 50}; 
     var width = 960 - margin.left - margin.right; 
     var height = 500 - margin.top - margin.bottom; 
     var parseDate = d3.time.format("%Y/%m/%d %H:%M:%S").parse; 

     var x = d3.time.scale() 
      .range([0, width]); 

     var y = d3.scale.linear() 
      .range([height, 0]); 

     var xAxis = d3.svg.axis() 
      .scale(x) 
      .orient("bottom"); 

     var yAxis = d3.svg.axis() 
      .scale(y) 
      .orient("left"); 

     var line = d3.svg.line() 
      .x(function(d) { return x(d.theTime); }) 
      .y(function(d) { return y(d.theValue); }); 


     var svg = d3.select("#myChart").append("svg") 
      .attr("width", width + margin.left + margin.right) 
      .attr("height", height + margin.top + margin.bottom) 
     .append("g") 
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

     dataset.forEach(function(d) { 
      d.theTime = parseDate(d.theTime); 
      d.theValue = parseFloat(d.theValue); 
     }); 

     x.domain(d3.extent(dataset, function(d) { return d.theTime; })); 
     y.domain(d3.extent(dataset, function(d) { return d.theValue;})); 

     svg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + height + ")") 
       .call(xAxis); 

     svg.append("g") 
       .attr("class", "y axis") 
       .call(yAxis) 
       .append("text") 
       .attr("transform", "rotate(-90)") 
       .attr("y", 6) 
       .attr("dy", ".71em") 
       .style("text-anchor", "end") 
       .text("M³/hr"); 

     svg.append("path") 
       .datum(dataset) 
       .attr("class", "line") 
       .attr("d", line); 
    }); 

     //~~~ Format The Date: 
     function formattedDateTime(dateAndTime) { 
      var d = new Date(dateAndTime); 
      var numDate = d.getDate(); 
      var numMonth = d.getMonth() + 1; 
      var numYear = d.getFullYear(); 
      var numHours = d.getHours(); 
      var numMinutes = d.getMinutes(); 
      var numSeconds = d.getSeconds(); 
      numDate = (numDate < 10) ? "0" + numDate : numDate; 
      numMonth = (numMonth < 10) ? "0" + numMonth : numMonth; 
      numHours = (numHours < 10) ? "0" + numHours : numHours; 
      numMinutes = (numMinutes < 10) ? "0" + numMinutes : numMinutes; 
      numSeconds = (numSeconds < 10) ? "0" + numSeconds : numSeconds; 

      return numYear + "/" + numMonth + "/" + numDate + " " + numHours + ":" + numMinutes + ":" + numSeconds; 
     }; 

+0

Привет @WebFixItMan, вы могли бы совместно использовать объект данных «dataSet» после выполнения цикла for в вершина. Я считаю, что основная причина обеих ошибок связана с выходом функции formattedDateTime. – Alex

+0

Какая версия D3? –

+0

Привет, Алекс и Херардо! Я считаю, что ответ Кирилла отвечает на вопрос Алекса. Для Херардо я использую ссылку CDN: \t '' – WebFixItMan

ответ

3

Проблема является датой вы передаете в этом формате:

'2016/07/12 15:58:40'

и функция parsedate вы сделали, чтобы разобрать это (Обратите внимание, что нет дефиса в настоящее время):

var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse; 

он должен были

var parseDate = d3.time.format("%Y/%m/%d %H:%M:%S").parse; 

Следующая ошибка, вы передаете данные для получения степени, но его нигде не определено:

x.domain(d3.extent(data, function(d) { return d.theTime; })); 
y.domain(d3.extent(data, function(d) { return d.theValue;})); 

Это должно было быть:

x.domain(d3.extent(dataset, function(d) { 
    return d.theTime; 
})); 
y.domain(d3.extent(dataset, function(d) { 
    return d.theValue; 
})); 

рабочий код here

+0

Привет Кирилл: Ваш совет почти прояснил путь к успеху. Это дало мне направление для решения этого. Я все еще получаю 'Uncaught TypeError: Не могу прочитать свойство 'length' undefined'. Мой дисплей также работал, когда я жестко закодировал переменную «набор данных», как ваш пример на JSFiddle. Однако в моей версии я ограничился использованием динамической переменной «набор данных». Я выполнил «alert (typeof (dataset)) перед функцией« dataset.forEach »и сообщил об этом как« объект ». Я собираюсь начать исследовать, как преодолеть это, но если у вас есть понимание, я очень ценю отзывы. – WebFixItMan

Смежные вопросы