el4251
el4251

Reputation: 49

D3 v5: "d" attribute in <path> tag not populating with values

Currently trying to create a simple line chart with D3 but I'm having some difficulties getting the data to display. The code seems to work (axes are generated fine) but for some reason, the "d" attribute in the tag is nonexistent when I run the code. The "fill," "stroke," and "stroke-width" attributes show up fine.

It appears that the line generator function I created is never used (see the console.logs below). I'm also not getting any errors.

d3.csv("./data/myFile.csv").then(d => {
        return { 
            percentile: d.percentile, 
            y50: +d.y50
        };
    }).then(data => {
        var xScale = d3.scalePoint()
            .domain(myDomain)
            .range([0, width])
            .padding(.5);
        svg.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(xScale));

        var yScale = d3.scaleLinear()
            .domain([0, 100])
            .range([height, 0]);
        svg.append("g")
            .call(d3.axisLeft(yScale));

        let line = d3.line()
            .x(d => {
                console.log("THIS DOES NOT PRINT TO CONSOLE");
                return xScale(d.percentile);
            })
            .y(d => {return yScale(d.y50)});

        console.log('THIS PRINTS TO CONSOLE');

        svg.append("path")
            .datum(data)
            .attr("d", line)
            .attr("fill", "none")
            .attr("stroke", "steelblue")
            .attr("stroke-width", 1.5);

        console.log('THIS PRINTS TO CONSOLE');
    });

This is what I see in the browser (I expect there to be a "d=..." attribute as well):

<path fill="none" stroke="steelblue" stroke-width="1.5"></path>

Edit: Here's a screenshot of what I see in the browser: Screenshot

Here's the first few rows of data:

percentile,y50
P0-10,16.10
P10-20,17.10
P20-30,18.50
P30-40,19.00
P40-50,19.20

Upvotes: 0

Views: 660

Answers (2)

Tom
Tom

Reputation: 2944

To explain the problem that was found here in the comments for future reference:

Rather than converting all the returned rows into the expected data format, the first .then is just returning a single object with:

{ 
    percentile: undefined, 
    y50: NaN
} 

What needs to happen here is to loop, or map, over the original data, and return the transformed object for each row i.e.

.then(data => {
    return data.map(d => {
        return { percentile: d.percentile, y50: +d.y50 }
    }
));

Upvotes: 1

JD333
JD333

Reputation: 533

d3.csv("./data/myFile.csv").then(data => {
      data.forEach(function(d) {
        d.y50 = +d.y50;
      });
        var xScale = d3.scalePoint()
            .domain(myDomain)
            .range([0, width])
            .padding(.5);
        svg.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(xScale));

        var yScale = d3.scaleLinear()
            .domain([0, 100])
            .range([height, 0]);
        svg.append("g")
            .call(d3.axisLeft(yScale));

        let line = d3.line()
            .x(d => {
                console.log("THIS DOES NOT PRINT TO CONSOLE");
                return xScale(d.percentile);
            })
            .y(d => {return yScale(d.y50)});

        console.log('THIS PRINTS TO CONSOLE');

        svg.append("path")
            .datum(data)
            .attr("d", line)
            .attr("fill", "none")
            .attr("stroke", "steelblue")
            .attr("stroke-width", 1.5);

        console.log('THIS PRINTS TO CONSOLE');
    });

This should fix your problem. You're original second then statement never retained the transformed data in your first then statement.

Upvotes: 1

Related Questions