【问题标题】:Parsing Time Series Data using D3.js使用 D3.js 解析时间序列数据
【发布时间】:2016-11-15 10:13:18
【问题描述】:

是时候寻求帮助了。我已经学习 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()”函数中,即“Uncaught TypeError: Cannot read property 'length' of undefined”。我在那里解析数据的努力源于代码中的“svg.append(“path”)”点发生的另一个错误,即“Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…”。

【问题讨论】:

  • 嗨@WebFixItMan,你能在顶部执行for循环后分享数据对象“dataSet”吗?我相信这两个错误的主要原因来自formattedDateTime函数的输出。
  • 什么版本的 D3?
  • 嗨亚历克斯和杰拉尔多!我相信西里尔的回答回答了亚历克斯的问题。对于 Gerardo,我使用的是 CDN 链接:<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

标签: d3.js svg time-series timeserieschart


【解决方案1】:

问题是您传递的日期是这种格式:

'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

【讨论】:

  • 嗨西里尔:您的建议几乎扫清了通往成功的道路。它给了我解决这个问题的方向。我仍然收到Uncaught TypeError: Cannot read property 'length' of undefined。当我像您在 JSFiddle 上的示例一样对变量“数据集”进行硬编码时,我的显示也有效。但是,在我的版本中,我仅限于使用动态“数据集”变量。我在“dataset.forEach”函数之前执行了alert(typeof(dataset)),并将其报告为“对象”。我将开始研究如何克服这个问题,但如果您有见解,我将非常感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 2015-04-11
  • 2015-12-15
  • 1970-01-01
  • 2013-07-31
  • 2017-05-25
  • 1970-01-01
  • 2013-03-24
  • 2015-12-11
相关资源
最近更新 更多