D3线图与一轴上的日期:缺少什么

时间:2018-03-11 11:25:29

标签: javascript d3.js data-visualization

...我正在开展一个打算提供D3折线图的项目,但我的数据模型看起来很糟糕。

图表的轴似乎很好,所以我认为数据模型很好,但是没有线条绘制,并且函数会因错误而停止,这意味着数据不正确。< / p>

(累了,我想去机场......如果有关于我如何在这里处理数据的明显信息,请原谅我......)

以下是显着的代码段:

<svg id="chart_space" width="800" height="400"></svg>

<script>

var ymd =  d3.timeParse('%Y-%m-%d');

DrawChart(); // everything in that function

function DrawChart() {

    var static_data = {
        "currency": "GBP",
        "prices": [
            {
                "date": "2015-02-28",
                "marketPrice": 392
            },
            {
                "date": "2015-03-31",
                "marketPrice": 394
            }
        ]
    };

var priceHistory = static_data['prices'];

var vis = d3.select("#chart_space"),
    WIDTH = 800,
    HEIGHT = 400,
    MARGINS = {
      top: 18,
      right: 18,
      bottom: 18,
      left: 35
    },
    xRange = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(priceHistory, function (d) {
        var dd = ymd(d.date);
        return dd;
      }),
      d3.max(priceHistory, function (d) {
        return ymd(d.date);
      })
    ]),

    yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(priceHistory, function (d) {
        return d.marketPrice;
      }),
      d3.max(priceHistory, function (d) {
        return d.marketPrice;
      })
    ]),

    // the axes on this chart draw okay. I have to think xRange is okay
    xAxis = d3.svg.axis()
      .scale(xRange)
      .tickSize(5)
      .tickSubdivide(true),

    yAxis = d3.svg.axis()
      .scale(yRange)
      .tickSize(5)
      .orient("left")
      .tickSubdivide(true);

  vis.append("svg:g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
    .call(xAxis);

  vis.append("svg:g")
    .attr("class", "y axis")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
    .call(yAxis);

// this is where mayhem begins -- we get NaN in the log traces here
var lineFunc = d3.svg.line()
  .x(function (d) {
    var xd = xRange(d.date);
    //console.log('X data to be plotted is: ' + xd); // emits NaN
    return xRange(d.date);
  })
  .y(function (d) {
    var yd = yRange(d.date); // (EDIT) okay, this is an error!
    //console.log('Y data to be plotted is: ' + yd);          
    return yRange(d.marketPrice);
  })
  .interpolate('linear');

vis.append("svg:path")
  .attr("d", lineFunc(priceHistory))
  .attr("stroke", "blue")
  .attr("stroke-width", 2)
  .attr("fill", "none");

}
</script>

控制台有一个屏幕截图:

console condition

我怀疑它与模型中的日期信息有关,但我无法理解为什么数字数据也会显示为NaN。 (编辑:因为代码中注释了错误)

我很确定我做了一些异色的事,但看不出什么,我的视力正在逐渐消失。

想法?

1 个答案:

答案 0 :(得分:2)

首先,这不是D3 v3:

var ymd =  d3.timeParse('%Y-%m-%d');

应该是:

var ymd =  d3.time.format('%Y-%m-%d');
ymd.parse(string);

回到问题:您的代码问题在于您只在计算域时解析日期。数据数组保留字符串。

因此,解决方案是解析数据数组中的日期:

priceHistory.forEach(function(d) {
    d.date = ymd.parse(d.date)
});

以下是您更改的代码:

var ymd = d3.time.format('%Y-%m-%d');

DrawChart(); // everything in that function

function DrawChart() {

  var static_data = {
    "currency": "GBP",
    "prices": [{
        "date": "2015-02-28",
        "marketPrice": 392
      },
      {
        "date": "2015-03-31",
        "marketPrice": 394
      }
    ]
  };

  var priceHistory = static_data['prices'];

  priceHistory.forEach(function(d) {
    d.date = ymd.parse(d.date)
  });

  var vis = d3.select("#chart_space"),
    WIDTH = 800,
    HEIGHT = 400,
    MARGINS = {
      top: 18,
      right: 18,
      bottom: 18,
      left: 35
    },
    xRange = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(priceHistory, function(d) {
        return d.date;
      }),
      d3.max(priceHistory, function(d) {
        return d.date;
      })
    ]),

    yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(priceHistory, function(d) {
        return d.marketPrice;
      }),
      d3.max(priceHistory, function(d) {
        return d.marketPrice;
      })
    ]),

    // the axes on this chart draw okay. I have to think xRange is okay
    xAxis = d3.svg.axis()
    .scale(xRange)
    .tickSize(5)
    .tickSubdivide(true),

    yAxis = d3.svg.axis()
    .scale(yRange)
    .tickSize(5)
    .orient("left")
    .tickSubdivide(true);

  vis.append("svg:g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
    .call(xAxis);

  vis.append("svg:g")
    .attr("class", "y axis")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
    .call(yAxis);

  // this is where mayhem begins -- we get NaN in the log traces here
  var lineFunc = d3.svg.line()
    .x(function(d) {
      var xd = xRange(d.date);
      //console.log('X data to be plotted is: ' + xd); // emits NaN
      return xRange(d.date);
    })
    .y(function(d) {
      var yd = yRange(d.date); // (EDIT) okay, this is an error!
      //console.log('Y data to be plotted is: ' + yd);          
      return yRange(d.marketPrice);
    })
    .interpolate('linear');

  vis.append("svg:path")
    .attr("d", lineFunc(priceHistory))
    .attr("stroke", "blue")
    .attr("stroke-width", 2)
    .attr("fill", "none");

}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg id="chart_space" width="800" height="400"></svg>