5

I want to create a multi series line chart with D3 based on this example. My problem is, that some of the values are missing:

y    x1   x2   x3
1   0.8       0.7
2   0.9       0.7
3   0.9  1.2  0.7
4        1.1  0.7
5   0.8  1.1  2.7
6   0.9  1.2  2.6
7        1.3  0.8

I want to get the following chart:

chart

Missing points at the beginnig or end should be left out. I could achieve that with

d3.svg.line().defined(function (d) { return d.value; }

But if some points are missing within a line, the line shouldn't be interrupted. With the code above the green line (x1) stops at y=3 and continues at y=5. But I want to have those points connected.

Without the usage of line().defined(), all missing points were handled as if their value was 0.

Here is the code, I used to find a way to implement that feature:

http://jsfiddle.net/G5z4N/2/

I think it is no solution for me to substitute the missing points in the data array before passing it to my charts function, because I have to show the values in a legend and in tooltips and I cannot show calculated values here. So for example if I move with the mouse over y=4, there should appear x1:-- x2:1.1 x3:0.8 in the legend (x1 does not have any value here). Also the (real) points should be displayed as circles. I also don't want to have two data tables in the memory (one with the real measurement data and a second with the augmented data for the chart lines).

stofl
  • 2,950
  • 6
  • 35
  • 48
  • For the part where you want the line to be connected if its missing value in the middle and not be connected if its missing its value in the front or back: May be if you can loop through your data and find first and last defined value for each of your X* columns then in the defined(function(d,i){if (i < x*Defined[first] || i> x*Defined[Last]) return false; else return true;}) – Yogesh Jul 29 '13 at 16:42
  • Hi @stofl, could you please indicate which section of the code enables the missing values to be treated as 0 please. I am struggling to make this happen. So far, they just dont appear on the graph. Thanks, – DaRoGa Feb 25 '16 at 14:13
  • The difference is between the function `line1` (line 12) and `line2` (line 16). As far as I remember, the function `x()` in line 13 returned `0` when the value is `null`. – stofl Mar 07 '16 at 18:19

1 Answers1

3

I could solve it, but I'm not sure if I can handle data updates this way with transitions. I changed the data format a bit and am drawing each line separately now:

http://jsfiddle.net/G5z4N/3/

var data = [
    {
        name: "x1",
        color: "green",
        data: [
            [1, 0.8],
            [2, 0.9],
            [3, 0.9],
            [5, 0.8],
            [6, 0.9]
        ]
    },
    {
        name: "x2",
        color: "red",
        data: [
            [3, 1.2],
            [4, 1.1],
            [5, 1.1],
            [6, 1.2],
            [7, 1.3]
        ]
    },
    {
        name: "x3",
        color: "blue",
        data: [
            [1, 0.7],
            [2, 0.7],
            [3, 0.7],
            [4, 0.7],
            [5, 2.7],
            [6, 2.6],
            [7, 0.8]
        ]
    },
];

var margin = [20, 20, 20, 20];
var w = 400 - margin[1] - margin[3];
var h = 300 - margin[0] - margin[2];

var x = d3.time.scale().range([0, w]);
var y = d3.scale.linear().range([h, 0]);
var lineFunction = d3.svg.line()
    .x(function(d) { return x(d[0]); })
    .y(function(d) { return y(d[1]); });

graph = d3.select('#line')
    .append("svg:svg")
        .attr("class", "line-graph")
        .attr("width", w + margin[1] + margin[3])
        .attr("height", h + margin[0] + margin[2])  
    .append("svg:g")
        .attr("transform", "translate(" + margin[3] + "," + margin[0] + ")");

x.domain([
    d3.min(data, function(c) { return d3.min(c.data, function(v) { return v[0]; }); }),
    d3.max(data, function(c) { return d3.max(c.data, function(v) { return v[0]; }); })
]);

y.domain([
    d3.min(data, function(c) { return d3.min(c.data, function(v) {  return +v[1]; }); }),
    d3.max(data, function(c) { return d3.max(c.data, function(v) { return +v[1]; }); })
]);

var linesGroup = graph
    .append("svg:g")
        .attr("class", "lines");

var linedata;
for (var i in data) {
    linedata = data[i];
    linesGroup
        .append("path")
            .attr("d", lineFunction(linedata.data))
            .attr("class", "line")
            .attr("fill", "none")
            .attr("stroke", function(d, i) {
                console.log(linedata.color);
                return linedata.color;
            });
};
stofl
  • 2,950
  • 6
  • 35
  • 48