使用D3中的.defined()处理缺少的时间序列数据

时间:2017-11-25 06:22:01

标签: javascript d3.js time-series

以下代码为values中的每个数组生成时间序列。

'use strict';
var times = [new Date(1511589600000),new Date(1511589660000),new Date(1511589720000),new Date(1511589780000),new Date(1511589840000),new Date(1511589900000),new Date(1511589960000),new Date(1511590020000),new Date(1511590080000),new Date(1511590140000),new Date(1511590200000),new Date(1511590260000),new Date(1511590320000),new Date(1511590380000),new Date(1511590440000),new Date(1511590500000),new Date(1511590560000),new Date(1511590620000),new Date(1511590680000),new Date(1511590740000),new Date(1511590800000),new Date(1511590860000),new Date(1511590920000),new Date(1511590980000),new Date(1511591040000),new Date(1511591100000),new Date(1511591160000),new Date(1511591220000),new Date(1511591280000),new Date(1511591340000),new Date(1511591400000),new Date(1511591460000),new Date(1511591520000),new Date(1511591580000),new Date(1511591640000),new Date(1511591700000),new Date(1511591760000),new Date(1511591820000),new Date(1511591880000),new Date(1511591940000),new Date(1511592000000),new Date(1511592060000),new Date(1511592120000),new Date(1511592180000),new Date(1511592240000),new Date(1511592300000),new Date(1511592360000),new Date(1511592420000),new Date(1511592480000),new Date(1511592540000),new Date(1511592600000),new Date(1511592660000),new Date(1511592720000),new Date(1511592780000),new Date(1511592840000),new Date(1511592900000),new Date(1511592960000),new Date(1511593020000),new Date(1511593080000),new Date(1511593140000),new Date(1511593200000)];
var values = [[25.44,25.44,25.44,25.44,25.44,25.44,25.752,26.064,26.376,26.688,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27],[9266,9266,9266,9182.5,9099,9278,9158,9184,9137,9126.5,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116,9116]];
var svg_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
    svg_height = 500;
var svg = d3.select('#svg'),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    chart_width = svg_width - margin.left - margin.right,
    chart_height = svg_height - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.attr('width', svg_width).attr('height', svg_height);
var xScale = d3.scaleTime().domain([times[0], times[times.length-1]]).range([0, chart_width]);
var yScale = d3.scaleLinear().domain([25.44, 9278]).range([chart_height, 0]);
var lineGenerator = d3.line()
  .x(function(d, i) { return xScale(times[i]); })
  .y(yScale)
  .curve(d3.curveCardinal);
values.forEach(function(curve, i) {
  var line = lineGenerator(curve);
  g.append('path').attr('d', line).attr("fill", "none")
      .attr("stroke", "steelblue")
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 1.5);
});
<svg id="svg"></svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js"></script>

但是,有时数据会为null。在这种情况下,我想在曲线中留下空白,如tutorial所示(搜索“假设我们的数据中有一个空白”,以找到教程中的确切位置)。该教程以及其他在线示例表明,可以使用lineGenerator.defined(function(d) { return d !== null; });完成此操作。但是,这不起作用:

'use strict';
var times = [new Date(1511589600000),new Date(1511589660000),new Date(1511589720000),new Date(1511589780000),new Date(1511589840000),new Date(1511589900000),new Date(1511589960000),new Date(1511590020000),new Date(1511590080000),new Date(1511590140000),new Date(1511590200000),new Date(1511590260000),new Date(1511590320000),new Date(1511590380000),new Date(1511590440000),new Date(1511590500000),new Date(1511590560000),new Date(1511590620000),new Date(1511590680000),new Date(1511590740000),new Date(1511590800000),new Date(1511590860000),new Date(1511590920000),new Date(1511590980000),new Date(1511591040000),new Date(1511591100000),new Date(1511591160000),new Date(1511591220000),new Date(1511591280000),new Date(1511591340000),new Date(1511591400000),new Date(1511591460000),new Date(1511591520000),new Date(1511591580000),new Date(1511591640000),new Date(1511591700000),new Date(1511591760000),new Date(1511591820000),new Date(1511591880000),new Date(1511591940000),new Date(1511592000000),new Date(1511592060000),new Date(1511592120000),new Date(1511592180000),new Date(1511592240000),new Date(1511592300000),new Date(1511592360000),new Date(1511592420000),new Date(1511592480000),new Date(1511592540000),new Date(1511592600000),new Date(1511592660000),new Date(1511592720000),new Date(1511592780000),new Date(1511592840000),new Date(1511592900000),new Date(1511592960000),new Date(1511593020000),new Date(1511593080000),new Date(1511593140000),new Date(1511593200000)];
var values = [[null,null,null,null,null,25.44,25.752,28.8,26.376,27.6,27,26.4,25.8,25.2,24.6,24,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],[null,null,9266,9182.5,9099,9278,9158,9527,8840,9126.5,9116,8841.5,8842,8842.5,8843,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]];
var svg_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
    svg_height = 500;
var svg = d3.select('#svg'),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    chart_width = svg_width - margin.left - margin.right,
    chart_height = svg_height - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.attr('width', svg_width).attr('height', svg_height);
var xScale = d3.scaleTime().domain([times[0], times[times.length-1]]).range([0, chart_width]);
var yScale = d3.scaleLinear().domain([, 9527]).range([chart_height, 0]);
var lineGenerator = d3.line()
  .defined(function(d) { return d !== null; })
  .x(function(d, i) { return xScale(times[i]); })
  .y(yScale)
  .curve(d3.curveCardinal);
values.forEach(function(curve, i) {
  var line = lineGenerator(curve);
  g.append('path').attr('d', line).attr("fill", "none")
      .attr("stroke", "steelblue")
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 1.5);
});
<svg id="svg"></svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js"></script>

我做错了什么?第一个和第二个代码块之间的唯一区别是第二个块有一些null值和.defined(function(d) { return d !== null; })行。

1 个答案:

答案 0 :(得分:0)

您的yScale域名不正确。现在是:

var yScale = d3.scaleLinear().domain([, 9527])
//no number here ---------------------^

它必须是两个值的数组,如下所示:

var yScale = d3.scaleLinear().domain([0, 9527])

以下是工作代码:

&#13;
&#13;
'use strict';
var times = [new Date(1511589600000),new Date(1511589660000),new Date(1511589720000),new Date(1511589780000),new Date(1511589840000),new Date(1511589900000),new Date(1511589960000),new Date(1511590020000),new Date(1511590080000),new Date(1511590140000),new Date(1511590200000),new Date(1511590260000),new Date(1511590320000),new Date(1511590380000),new Date(1511590440000),new Date(1511590500000),new Date(1511590560000),new Date(1511590620000),new Date(1511590680000),new Date(1511590740000),new Date(1511590800000),new Date(1511590860000),new Date(1511590920000),new Date(1511590980000),new Date(1511591040000),new Date(1511591100000),new Date(1511591160000),new Date(1511591220000),new Date(1511591280000),new Date(1511591340000),new Date(1511591400000),new Date(1511591460000),new Date(1511591520000),new Date(1511591580000),new Date(1511591640000),new Date(1511591700000),new Date(1511591760000),new Date(1511591820000),new Date(1511591880000),new Date(1511591940000),new Date(1511592000000),new Date(1511592060000),new Date(1511592120000),new Date(1511592180000),new Date(1511592240000),new Date(1511592300000),new Date(1511592360000),new Date(1511592420000),new Date(1511592480000),new Date(1511592540000),new Date(1511592600000),new Date(1511592660000),new Date(1511592720000),new Date(1511592780000),new Date(1511592840000),new Date(1511592900000),new Date(1511592960000),new Date(1511593020000),new Date(1511593080000),new Date(1511593140000),new Date(1511593200000)];
var values = [[null,null,null,null,null,25.44,25.752,28.8,26.376,27.6,27,26.4,25.8,25.2,24.6,24,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],[null,null,9266,9182.5,9099,9278,9158,9527,8840,9126.5,9116,8841.5,8842,8842.5,8843,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]];
var svg_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
    svg_height = 500;
var svg = d3.select('#svg'),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    chart_width = svg_width - margin.left - margin.right,
    chart_height = svg_height - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.attr('width', svg_width).attr('height', svg_height);
var xScale = d3.scaleTime().domain([times[0], times[times.length-1]]).range([0, chart_width]);
var yScale = d3.scaleLinear().domain([0, 9527]).range([chart_height, 0]);
var lineGenerator = d3.line()
  .defined(function(d) { return d !== null; })
  .x(function(d, i) { return xScale(times[i]); })
  .y(yScale)
  .curve(d3.curveCardinal);
values.forEach(function(curve, i) {
  var line = lineGenerator(curve);
  g.append('path').attr('d', line).attr("fill", "none")
      .attr("stroke", "steelblue")
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 1.5);
});
&#13;
<svg id="svg"></svg>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js"></script>
&#13;
&#13;
&#13;

PS:正如您所看到的,您的声明(&#34;第一个和第二个代码块之间的唯一区别是......&#34; )不正确。您可以使用在线差异检查器this one来捕获这些微小变化。此外,大多数优秀的代码编辑器都有一个diff工具。