时间序列多线折线图上的D3散点图

D3 scatterplot on time series multi-line line graph

我尝试在时间序列图上的每个数据点放置点(最终使用悬停工具提示)。 Here is the D3 Block

多线部分基于 this example,并创建了一个名为 draw() 的函数,该函数利用外部 d3.line() 生成器绘制图形。

我正在尝试在温度数据和时间相交的数据点上创建散点图点 - 这适用于直线但不适用于我的椭圆,我不确定我做错了什么。

The failing scatterplot attempt is here.

使圆圈与数据点重叠的最佳方法是什么?我在 JavaScript 调试器中遇到的错误是

d3.v4.js:1381 Error: <circle> attribute cx: Expected length, "NaN".
d3.v4.js:1381 Error: <circle> attribute cy: Expected length, "NaN".

数据解析似乎可以很好地处理直线交点,只是 cx 和 cy 坐标不行。

JavaScript 失败尝试如下:

// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

// parse the date / time
var parseDate = d3.timeParse("%Y-%m-%d %H:%M:%S");
var formatTime = d3.timeFormat("%e %B");

// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);

// define the div for the tooltip
var div = d3.select("body").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);


var tempprobe_line = d3.line()
    .x( function(d) { return x(d.timestamp); })
    .y( function(d) { return y(d.tempprobe); });

var high_threshold_line = d3.line()
    .x(function(d){ return x(d.timestamp); })
    .y(function(d){ return y(d.threshold_high); });

var low_threshold_line = d3.line()
    .x(function(d){
        return x(d.timestamp);
    })
    .y(function(d){
        return y(d.threshold_low);
    })


var ambient_line = d3.line()
    .x(function(d)
        { return x(d.timestamp);}
    )
    .y( function(d) {
        return y(d.ambient);
    });


var svg = d3.select("body").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 + ")");


function draw(data, tempdata) {

    var data = data[tempdata];

    data.forEach(function(d, i) {
        d.timestamp = parseDate(d.timestamp);
        d.tempprobe = +d.tempprobe;
        d.ambient = +d.ambient;
    });

    data.sort(function(a, b){
        return a["timestamp"]-b["timestamp"];
    });

    // scale the range of data
    x.domain(d3.extent(data, function(d){
        return d.timestamp;
    }));
    y.domain([0, d3.max(data, function(d){
        return Math.max(d.tempprobe, d.ambient);
    })]);

    // Add the tempprobe path.
    svg.append("path")
        .data([data])
        .attr("class", "line temp-probe temperature")
        .attr("d", tempprobe_line);

    // Add the ambient path
    svg.append("path")
        .data([data])
        .attr("class", "line ambient temperature")
        .attr("d", ambient_line);

    svg.append("path")
        .data([data])
        .attr("class", "line high-threshold")
        .attr("d", high_threshold_line)

    svg.append("path")
        .data([data])
        .attr("class", "line low-threshold")
        .attr("d", low_threshold_line)

    // add the X Axis
    svg.append("g")
        .attr("transform", "translate(0,"+ height + ")")
        .call(d3.axisBottom(x));

    // add the Y Axis
    svg.append("g")
        .call(d3.axisLeft(y));
    }

    d3.json("temp_data.json",
        function(error, data){
    if (error){
        throw error;
    }
    draw(data[0], "tempdata");
    // Add the scatterplot -- the failing part
    svg.selectAll("dot")
        .data(data)
      .enter().append("circle")
        .attr("r", 3.5)
        .attr("cx", function(d) { return x(d.timestamp); })
        .attr("cy", function(d) { return y(d.tempprobe); });
});

您传递给 selection.data() 函数的数据是错误的。您需要的数据嵌套在 data 变量中。

这对我有用:

svg.selectAll("dot")
   .data(data[0]['tempdata'])
   .enter()
   .append("circle")
   .attr("r", 3.5)
   .attr("cx", function(d) { return x(d.timestamp); })
   .attr("cy", function(d) { return y(d.tempprobe); });

这会在蓝色 tempprobe 线上的每个数据点上添加圆圈。