JBaldwin
JBaldwin

Reputation: 364

Error: <path> attribute d: expected number - when trying to build a line chart with D3

I'm trying to build a multiple line chart with D3. I'm pulling the data in from a HTML table and then trying to build the chart. I keep getting an error though and can't seem to figure out how to get it to a number and not get the NaN error anymore.

Here is my code:

        function plantVolumes() {

        //draw plant volumes table
        plantView = "<h4>Plant Volumes</h4><table id='dataTable' class='plantVolumeTable'><thead id='plantTableHead'><tr><th>Month Start Date</th><th>Volume Type</th><th>Volume</th><th>Unit</th><th class='hidden'>Volume Src</th></tr></thead><tbody>";
        for(i=0;i<plantData1.length;i++) {

            if(plantData1["MergeKey_lvl00"][i] == mergeKey) {
                //get volume type
                for(var j=0;j<plantData2.length;j++) {
                    if(plantData2["VolumeTypeId"][j] == plantData1["VolumeTypeId"][i]) {
                        var volumeType = plantData2["VolumeType"][j];
                        var volumeUnit = plantData2["Unit"][j];
                    }
                }
                //draw rows 
                plantView += "<tr><td>" + plantData1["MonthStartDate"][i] + "</td><td>" + volumeType + "</td><td>" + plantData1["Volume"][i] + "</td><td>" + volumeUnit + "</td><td class='hidden'>" + plantData1["Volume_src"][i] + "</td></tr>";  
            }
        }
        plantView += "</tbody></table>";

        $("#plantVolumesTableDiv").html(plantView);
        document.getElementById("plantViews").style.display = "block";

        initializeDataTable();
        //end draw plant volumes table

        //DRAW LINE CHART                   
        //set dimensions of canvas
        var margin = {top:30, right:20, bottom:30, left:50},
            width = 600 - margin.left - margin.right,
            height = 270 - margin.top - margin.bottom;

        //parse the date
        var parseDate = d3.time.format("%Y %b %d").parse;

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

        //define the axes
        var xAxis = d3.svg.axis().scale(x)
            .orient("bottom").ticks(12);
        var yAxis = d3.svg.axis().scale(y)
            .orient("left").ticks(5);

        //define the line
        var volumeLine = d3.svg.line()
            //.x( (d) => x(d.MonthStartDate) )
            .x(function(d) { return x(d.MonthStartDate); })
            .y(function(d) { return y(d.Volume); });

        //add svg to canvas
        var svg = d3.select("#volumeChart")
            //.data(data)
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        //get volume table data
        var data = $(".plantVolumeTable tbody").children().map(function() {
            var children = $(this).children();

            return {
                MonthStartDate: children.eq(0).text(),
                VolumeType: children.eq(1).text(),
                Volume: children.eq(2).text()
            };
        }).get();

        data.forEach(function(d) {
            d.MonthStartDate = d.MonthStartDate;
            //d.VolumeType = d.VolumeType;
            d.Volume = +d.Volume;
        });

        //console.log(data);

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

        //nest data
        var dataNest = d3.nest()
            .key(function(d) { return d.VolumeType; })
            .entries(data);
        console.log(dataNest);
        //loop through volume types / key
        dataNest.forEach(function(d) {

            svg.append("path")
                .attr("class", "line")
                .attr("d", volumeLine(d.values));
        });

        //add the x axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
        //add the y axis
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);
    }

Any thoughts on what I'm doing wrong or missing?

Upvotes: 1

Views: 1342

Answers (1)

lostInTheTetons
lostInTheTetons

Reputation: 1222

I modified your code a little bit. You needed to parse the date in both places, the line and the domain part. Also, you needed to fix your parseDate to be the correct format the way the table.

Here is my modified code:

        function plantVolumes() {

        //draw plant volumes table
        plantView = "<h4>Plant Volumes</h4><table id='dataTable' class='plantVolumeTable'><thead id='plantTableHead'><tr><th>Month Start Date</th><th>Volume Type</th><th>Volume</th><th>Unit</th><th class='hidden'>Volume Src</th></tr></thead><tbody>";
        for(i=0;i<plantData1.length;i++) {

            if(plantData1["MergeKey_lvl00"][i] == mergeKey) {
                //get volume type
                for(var j=0;j<plantData2.length;j++) {
                    if(plantData2["VolumeTypeId"][j] == plantData1["VolumeTypeId"][i]) {
                        var volumeType = plantData2["VolumeType"][j];
                        var volumeUnit = plantData2["Unit"][j];
                    }
                }
                //draw rows 
                plantView += "<tr><td>" + plantData1["MonthStartDate"][i] + "</td><td>" + volumeType + "</td><td>" + plantData1["Volume"][i] + "</td><td>" + volumeUnit + "</td><td class='hidden'>" + plantData1["Volume_src"][i] + "</td></tr>";  
            }
        }
        plantView += "</tbody></table>";

        $("#plantVolumesTableDiv").html(plantView);
        document.getElementById("plantViews").style.display = "block";

        initializeDataTable();
        //end draw plant volumes table

        //DRAW LINE CHART                   
        //set dimensions of canvas
        var margin = {top:30, right:20, bottom:30, left:50},
            width = 600 - margin.left - margin.right,
            height = 270 - margin.top - margin.bottom;

        //parse the date
        var parseDate = d3.time.format("%Y-%m-%d").parse;

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

        //define the axes
        var xAxis = d3.svg.axis().scale(x)
            .orient("bottom").ticks(12);
        var yAxis = d3.svg.axis().scale(y)
            .orient("left").ticks(5);

        //define the line
        var volumeLine = d3.svg.line()
            .x(function(d) { return x(parseDate(d.MonthStartDate)); })
            .y(function(d) { return y(d.Volume); });

        //add svg to canvas
        var svg = d3.select("#volumeChart")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        //get volume table data
        var data = $(".plantVolumeTable tbody").children().map(function() {
            var children = $(this).children();

            return {
                MonthStartDate: children.eq(0).text(),
                Volume: children.eq(2).text(),
                VolumeType: children.eq(1).text()
            };
        }).get();

        data.forEach(function(d) {
            d.MonthStartDate = d.MonthStartDate;
            d.VolumeType = d.VolumeType;
            d.Volume = +d.Volume;
        });

        //scale the domain of data
        x.domain(d3.extent(data, function(d) { return parseDate(d.MonthStartDate); }));
        y.domain([0, d3.max(data, function(d) { return d.Volume; })]);

        //nest data
        var dataNest = d3.nest()
            .key(function(d) { return d.VolumeType; })
            .entries(data);
        //loop through volume types / key
        dataNest.forEach(function(d) {

            svg.append("path")
                .attr("class", "line " + function(d) {return d.VolumeType;})
                .attr("d", volumeLine(d.values));
        });

        //add the x axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
        //add the y axis
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);   

    }

Upvotes: 1

Related Questions