D3折线图:x线函数始终呈现NaN

时间:2016-03-11 00:28:34

标签: javascript d3.js

好的,对于以下代码,我的x行函数返回NaN。我不知道为什么。我尝试将时间值更改为1到9并使用线性比例,我已将它们转换为时间(它仅用于概念证明,因此可以暂时调整值),并尝试将它们作为“新日期” ',没有运气。

我做错了什么?为什么X总是NaN?

其中一个记录数据点的示例:

x:d是:2015-06-01 x(新日期(d.Period))是NaN y:d是65.54347826086956

jQuery(document).ready(function ($) {


  var margin = {top: 20, right: 30, bottom: 40, left: 50},
  width = 300 - margin.left - margin.right,
  height = 150 - margin.top - margin.bottom;

  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 color = d3.scale.category10();

  var line = d3.svg.line()
    .x(function(d) {console.log('d is : ', d.Period,' x(new Date(d.Period)) is ', x(new Date(d.Period))); return x(new Date(d.Period)); })
    .y(function(d) {console.log('y:d is ', y(d.Value)); return y(d.Value); })

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

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

  // This separates the data into the lines we want, although the data is stored
  // In the same original object.
  var keys = color.domain(d3.keys(data[0].values[0]).filter(function(key) { 
    if (key === 'Amount'
     || key === 'Quantity') {
        return key
    }
  }));

  // This returns the data into two separate objects which can be graphed.
  // In this case, Amount and Quantity.
  var datasets = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {Period: d.values[0].Time, Value: +d.values[0][name]};
      })
    };
  });

  console.log('datasets is: ', datasets);

  // set the minYDomainValue to zero instead of letting it be a lingering magic number.
  var minDomainValue = 0

  // x.domain([
  //   minDomainValue,
  //   d3.max(datasets, function(c) { return d3.max(c.values, function(v) { console.log(v); return v.Time }); })
  // ])

  x.domain(d3.extent(datasets, function(d) { console.log(d); return new Date(d.values[0].Time); }));

  y.domain([
    minDomainValue,
    // d3.min(datasets, function(c) { return d3.min(c.values, function(v) { return v.Time; }); }),
    d3.max(datasets, function(c) { return d3.max(c.values, function(v) { return v.Value; }); })
  ])

  // Append the x-axis class and move axis around.
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)

  // Append the y-axis class.
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)

  var dataset = svg.selectAll('.pipeline')
    .data(datasets);

  console.log(dataset);

  dataset.enter()
    .append('g')
    .attr('class', 'pipeline');

  dataset.append('path')
    .attr('class', 'line')
    .attr('d', function(d) { return line(d.values); })
    .attr("data-legend",function(d) { return d.name})
    .style("stroke", function(d) { return color(d.name); })

  dataset.exit().remove()

});

var data = [
  {
    key: 1,
    values: [
      {
        Amount: 33,
        Quantity: 22,
        Time: '2015-01-01'
      }
    ]
  },
  {
    key: 2,
    values: [
      {
        Amount: 52,
        Quantity: 20,
        Time: '2015-02-01'
      }
    ]
  },
  {
    key: 3,
    values: [
      {
        Amount: 63,
        Quantity: 30,
        Time: '2015-03-01'
      }
    ]
  },
  {
    key: 4,
    values: [
      {
        Amount: 92,
        Quantity: 60,
        Time: '2015-04-01'
      }
    ]
  },
  {
    key: 5,
    values: [
      {
        Amount: 50,
        Quantity: 29,
        Time: '2015-05-01'
      }
    ]
  },
  {
    key: 6,
    values: [
      {
        Amount: 53,
        Quantity: 25,
        Time: '2015-06-01'
      }
    ]
  },
  {
    key: 7,
    values: [
      {
        Amount: 46,
        Quantity: 12,
        Time: '2015-07-01'
      }
    ]
  },
  {
    key: 8,
    values: [
      {
        Amount: 52,
        Quantity: 15,
        Time: '2015-08-01'
      }
    ]
  },
  {
    key: 9,
    values: [
      {
        Amount: 55,
        Quantity: 20,
        Time: '2015-09-01'
      }
    ]
  }
]

// var formatTime = function(date) {
//   var formatter = d3.time.format("%Y-%m").parse;
//   return formatter(date);
// }

1 个答案:

答案 0 :(得分:1)

要回答您的具体问题,您未正确设置x域名,我建议您:

var minDate = d3.min(datasets, function(d0){
  return d3.min(d0.values, function(d1){
    return d1.Period;
  })
}),
maxDate = d3.max(datasets, function(d0){
  return d3.max(d0.values, function(d1){
    return d1.Period;
  })
});
x.domain([minDate, maxDate]);

为了实现这一目标,请接受我的下一个建议并停止new Date(疯狂,只要强迫你的时间从一开始就过去。我强烈建议您使用generator expression而不是尝试自我转换:

var tP = d3.time.format("%Y-%m-%d");
// This returns the data into two separate objects which can be graphed.
// In this case, Amount and Quantity.
var datasets = color.domain().map(function(name) {
  return {
    name: name,
    values: data.map(function(d) {
      return {
        Period: tP.parse(d.values[0].Time), //<-- just convert once!
        Value: +d.values[0][name]
      };
    })
  };
});

然后将您的行功能简化为:

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

完整代码:

&#13;
&#13;
<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <svg id="pipeline-chart-render"></div>
  <script>
    var data = [{
      key: 1,
      values: [{
        Amount: 33,
        Quantity: 22,
        Time: '2015-01-01'
      }]
    }, {
      key: 2,
      values: [{
        Amount: 52,
        Quantity: 20,
        Time: '2015-02-01'
      }]
    }, {
      key: 3,
      values: [{
        Amount: 63,
        Quantity: 30,
        Time: '2015-03-01'
      }]
    }, {
      key: 4,
      values: [{
        Amount: 92,
        Quantity: 60,
        Time: '2015-04-01'
      }]
    }, {
      key: 5,
      values: [{
        Amount: 50,
        Quantity: 29,
        Time: '2015-05-01'
      }]
    }, {
      key: 6,
      values: [{
        Amount: 53,
        Quantity: 25,
        Time: '2015-06-01'
      }]
    }, {
      key: 7,
      values: [{
        Amount: 46,
        Quantity: 12,
        Time: '2015-07-01'
      }]
    }, {
      key: 8,
      values: [{
        Amount: 52,
        Quantity: 15,
        Time: '2015-08-01'
      }]
    }, {
      key: 9,
      values: [{
        Amount: 55,
        Quantity: 20,
        Time: '2015-09-01'
      }]
    }]

    var margin = {
        top: 20,
        right: 30,
        bottom: 40,
        left: 50
      },
      width = 300 - margin.left - margin.right,
      height = 150 - margin.top - margin.bottom;
      
    var tP = d3.time.format("%Y-%m-%d");

    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 color = d3.scale.category10();

    var line = d3.svg.line()
      .x(function(d) {
        
        console.log('d is : ', d.Period, ' x(new Date(d.Period)) is ', x(d.Period));
        return x(d.Period);
      })
      .y(function(d) {
        console.log('y:d is ', y(d.Value));
        return y(d.Value);
      })

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

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

    // This separates the data into the lines we want, although the data is stored
    // In the same original object.
    var keys = color.domain(d3.keys(data[0].values[0]).filter(function(key) {
      if (key === 'Amount' || key === 'Quantity') {
        return key
      }
    }));

    // This returns the data into two separate objects which can be graphed.
    // In this case, Amount and Quantity.
    var datasets = color.domain().map(function(name) {
      return {
        name: name,
        values: data.map(function(d) {
          return {
            Period: tP.parse(d.values[0].Time),
            Value: +d.values[0][name]
          };
        })
      };
    });

    // set the minYDomainValue to zero instead of letting it be a lingering magic number.
    var minDomainValue = 0;

    var minDate = d3.min(datasets, function(d0){
      return d3.min(d0.values, function(d1){
        return d1.Period;
      })
    }),
    maxDate = d3.max(datasets, function(d0){
      return d3.max(d0.values, function(d1){
        return d1.Period;
      })
    });
    x.domain([minDate, maxDate]);

    y.domain([
      minDomainValue,
      // d3.min(datasets, function(c) { return d3.min(c.values, function(v) { return v.Time; }); }),
      d3.max(datasets, function(c) {
        return d3.max(c.values, function(v) {
          return v.Value;
        });
      })
    ])

    // Append the x-axis class and move axis around.
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)

    // Append the y-axis class.
    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)

    var dataset = svg.selectAll('.pipeline')
      .data(datasets);

    console.log(dataset);

    dataset.enter()
      .append('g')
      .attr('class', 'pipeline');

    dataset.append('path')
      .attr('class', 'line')
      .attr('d', function(d) {
        return line(d.values);
      })
      .attr("data-legend", function(d) {
        return d.name
      })
      .style("stroke", function(d) {
        return color(d.name);
      })

    dataset.exit().remove()
  </script>
</body>

</html>
&#13;
&#13;
&#13;

相关问题