最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Error: <line> attribute y1: Expected length, "NaN" - Stack Overflow

programmeradmin1浏览0评论

I am trying to display a boxplot with d3 v3 and I get the error mentioned along with others from the same kind:

Error: <line> attribute y2: Expected length, "NaN".

Error: <rect> attribute y: Expected length, "NaN".

Full error message:

Error: attribute y: Expected length, "NaN". o @ d3.v3.min.js:1 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 da.attr @ d3.v3.min.js:3 (anonymous) @ box.js:103 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 box @ box.js:19 da.call @ d3.v3.min.js:3 (anonymous) @ subject:262 (anonymous) @ d3.v3.min.js:1 t @ d3.v3.min.js:1 u @ d3.v3.min.js:1 load (async) St @ d3.v3.min.js:1 e @ d3.v3.min.js:3 (anonymous) @ subject:170

I got the js code from a website so I just changed the parameters they mentioned... The js code of the chart is the following:

var labels = true; // show the text labels beside individual boxplots?
var margin = {
    top: 30,
    right: 50,
    bottom: 70,
    left: 50
};
var width = 800 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;

var min = 1000,
    max = -1000;

// parse in the data    
d3.csv("../static/CSV/Chart_data/boxplot_year.csv?rnd='+(new Date).getTime()", function(error, csv) {
    // using an array of arrays with
    // data[n][2] 
    // where n = number of columns in the csv file 
    // data[i][0] = name of the ith column
    // data[i][1] = array of values of ith column

    var data = [];
    data[0] = [];
    data[1] = [];
    data[2] = [];
    data[3] = [];
    data[4] = [];
    data[5] = [];
    // add more rows if your csv file has more columns

    // add here the header of the csv file
    data[0][0] = "Y1";
    data[1][0] = "Y2";
    data[2][0] = "Y3";
    data[3][0] = "Y4";
    data[4][0] = "Y5";
    data[5][0] = "Y6";
    // add more rows if your csv file has more columns

    data[0][1] = [];
    data[1][1] = [];
    data[2][1] = [];
    data[3][1] = [];
    data[4][1] = [];
    data[5][1] = [];

    csv.forEach(function(x) {
        var v1 = Math.floor(x.Y1),
            v2 = Math.floor(x.Y2),
            v3 = Math.floor(x.Y3),
            v4 = Math.floor(x.Y4),
            v5 = Math.floor(x.Y5),
            v6 = Math.floor(x.Y6);
        // add more variables if your csv file has more columns

        var rowMax = Math.max(Math.max(v1, v2), Math.max(Math.max(v3, v4), Math.max(v5, v6)));
        var rowMin = Math.min(Math.min(v1, v2), Math.min(Math.min(v3, v4), Math.min(v5, v6)));

        data[0][1].push(v1);
        data[1][1].push(v2);
        data[2][1].push(v3);
        data[3][1].push(v4);
        data[4][1].push(v5);
        data[5][1].push(v6);
        // add more rows if your csv file has more columns

        if (rowMax > max) max = rowMax;
        if (rowMin < min) min = rowMin;
    });

    var chart = d3.box()
        .whiskers(iqr(1.5))
        .height(height)
        .domain([min, max])
        .showLabels(labels);

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("class", "box")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // the x-axis
    var x = d3.scale.ordinal()
        .domain(data.map(function(d) {
            console.log(d);
            return d[0];
        }))
        .rangeRoundBands([0, width], 0.7, 0.3);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    // the y-axis
    var y = d3.scale.linear()
        .domain([min, max])
        .range([height + margin.top, 0 + margin.top]);

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

    // draw the boxplots    
    svg.selectAll(".box")
        .data(data)
        .enter().append("g")
        .attr("transform", function(d) {
            return "translate(" + x(d[0]) + "," + margin.top + ")";
        })
        .call(chart.width(x.rangeBand()));


    // add a title
    svg.append("text")
        .attr("x", (width / 2))
        .attr("y", 0 + (margin.top / 2))
        .attr("text-anchor", "middle")
        .style("font-size", "18px")
        //.style("text-decoration", "underline")  
        .text("Grade through the years");

    // draw y axis
    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("Grade") // and text1
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .style("font-size", "16px")
        .text("Revenue in €");

    // draw x axis  
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + (height + margin.top + 10) + ")")
        .call(xAxis)
        .append("Year") // text label for the x axis
        .attr("x", (width / 2))
        .attr("y", 10)
        .attr("dy", ".71em")
        .style("text-anchor", "middle")
        .style("font-size", "16px")
        .text("Quarter");
});

// Returns a function to pute the interquartile range.
function iqr(k) {
    return function(d, i) {
        var q1 = d.quartiles[0],
            q3 = d.quartiles[2],
            iqr = (q3 - q1) * k,
            i = -1,
            j = d.length;
        while (d[++i] < q1 - iqr);
        while (d[--j] > q3 + iqr);
        return [i, j];
    };
}

And my csv file is:

Y1,Y2,Y3,Y4,Y5,Y6

3.8,5.7,0.0,6.8,8.2,6.8

5.0,1.5,5.0,0.0,6.1,9.0

4.0,5.6,5.5,4.1,5.5,5.1

5.4,6.7,5.1,5.0,9.0,6.8

5.5,5.3,8.0,8.6,6.1,7.7

8.0,1.7,4.6,6.1,7.6,5.9

6.3,7.3,6.8,8.3,6.0,0.0

5.0,5.1,6.6,7.8,5.4,3.5

5.6,3.7,7.0,5.1,7.1,2.7

8.5,6.0,1.8,7.7,2.5,8.0

6.4,9.8,5.8,7.0,6.8,8.7

6.7,7.5,5.0,6.3,0.0,7.4

Any ideas? Thank you in advance!

I am trying to display a boxplot with d3 v3 and I get the error mentioned along with others from the same kind:

Error: <line> attribute y2: Expected length, "NaN".

Error: <rect> attribute y: Expected length, "NaN".

Full error message:

Error: attribute y: Expected length, "NaN". o @ d3.v3.min.js:1 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 da.attr @ d3.v3.min.js:3 (anonymous) @ box.js:103 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 box @ box.js:19 da.call @ d3.v3.min.js:3 (anonymous) @ subject:262 (anonymous) @ d3.v3.min.js:1 t @ d3.v3.min.js:1 u @ d3.v3.min.js:1 load (async) St @ d3.v3.min.js:1 e @ d3.v3.min.js:3 (anonymous) @ subject:170

I got the js code from a website so I just changed the parameters they mentioned... The js code of the chart is the following:

var labels = true; // show the text labels beside individual boxplots?
var margin = {
    top: 30,
    right: 50,
    bottom: 70,
    left: 50
};
var width = 800 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;

var min = 1000,
    max = -1000;

// parse in the data    
d3.csv("../static/CSV/Chart_data/boxplot_year.csv?rnd='+(new Date).getTime()", function(error, csv) {
    // using an array of arrays with
    // data[n][2] 
    // where n = number of columns in the csv file 
    // data[i][0] = name of the ith column
    // data[i][1] = array of values of ith column

    var data = [];
    data[0] = [];
    data[1] = [];
    data[2] = [];
    data[3] = [];
    data[4] = [];
    data[5] = [];
    // add more rows if your csv file has more columns

    // add here the header of the csv file
    data[0][0] = "Y1";
    data[1][0] = "Y2";
    data[2][0] = "Y3";
    data[3][0] = "Y4";
    data[4][0] = "Y5";
    data[5][0] = "Y6";
    // add more rows if your csv file has more columns

    data[0][1] = [];
    data[1][1] = [];
    data[2][1] = [];
    data[3][1] = [];
    data[4][1] = [];
    data[5][1] = [];

    csv.forEach(function(x) {
        var v1 = Math.floor(x.Y1),
            v2 = Math.floor(x.Y2),
            v3 = Math.floor(x.Y3),
            v4 = Math.floor(x.Y4),
            v5 = Math.floor(x.Y5),
            v6 = Math.floor(x.Y6);
        // add more variables if your csv file has more columns

        var rowMax = Math.max(Math.max(v1, v2), Math.max(Math.max(v3, v4), Math.max(v5, v6)));
        var rowMin = Math.min(Math.min(v1, v2), Math.min(Math.min(v3, v4), Math.min(v5, v6)));

        data[0][1].push(v1);
        data[1][1].push(v2);
        data[2][1].push(v3);
        data[3][1].push(v4);
        data[4][1].push(v5);
        data[5][1].push(v6);
        // add more rows if your csv file has more columns

        if (rowMax > max) max = rowMax;
        if (rowMin < min) min = rowMin;
    });

    var chart = d3.box()
        .whiskers(iqr(1.5))
        .height(height)
        .domain([min, max])
        .showLabels(labels);

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("class", "box")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // the x-axis
    var x = d3.scale.ordinal()
        .domain(data.map(function(d) {
            console.log(d);
            return d[0];
        }))
        .rangeRoundBands([0, width], 0.7, 0.3);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    // the y-axis
    var y = d3.scale.linear()
        .domain([min, max])
        .range([height + margin.top, 0 + margin.top]);

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left");

    // draw the boxplots    
    svg.selectAll(".box")
        .data(data)
        .enter().append("g")
        .attr("transform", function(d) {
            return "translate(" + x(d[0]) + "," + margin.top + ")";
        })
        .call(chart.width(x.rangeBand()));


    // add a title
    svg.append("text")
        .attr("x", (width / 2))
        .attr("y", 0 + (margin.top / 2))
        .attr("text-anchor", "middle")
        .style("font-size", "18px")
        //.style("text-decoration", "underline")  
        .text("Grade through the years");

    // draw y axis
    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("Grade") // and text1
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .style("font-size", "16px")
        .text("Revenue in €");

    // draw x axis  
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + (height + margin.top + 10) + ")")
        .call(xAxis)
        .append("Year") // text label for the x axis
        .attr("x", (width / 2))
        .attr("y", 10)
        .attr("dy", ".71em")
        .style("text-anchor", "middle")
        .style("font-size", "16px")
        .text("Quarter");
});

// Returns a function to pute the interquartile range.
function iqr(k) {
    return function(d, i) {
        var q1 = d.quartiles[0],
            q3 = d.quartiles[2],
            iqr = (q3 - q1) * k,
            i = -1,
            j = d.length;
        while (d[++i] < q1 - iqr);
        while (d[--j] > q3 + iqr);
        return [i, j];
    };
}

And my csv file is:

Y1,Y2,Y3,Y4,Y5,Y6

3.8,5.7,0.0,6.8,8.2,6.8

5.0,1.5,5.0,0.0,6.1,9.0

4.0,5.6,5.5,4.1,5.5,5.1

5.4,6.7,5.1,5.0,9.0,6.8

5.5,5.3,8.0,8.6,6.1,7.7

8.0,1.7,4.6,6.1,7.6,5.9

6.3,7.3,6.8,8.3,6.0,0.0

5.0,5.1,6.6,7.8,5.4,3.5

5.6,3.7,7.0,5.1,7.1,2.7

8.5,6.0,1.8,7.7,2.5,8.0

6.4,9.8,5.8,7.0,6.8,8.7

6.7,7.5,5.0,6.3,0.0,7.4

Any ideas? Thank you in advance!

Share Improve this question edited May 9, 2018 at 5:39 MTT asked May 8, 2018 at 16:25 MTTMTT 3791 gold badge6 silver badges21 bronze badges 9
  • Math.floor(x,2010), <-- why the 2010? – epascarello Commented May 8, 2018 at 16:28
  • Do you know where the error is being thrown? Does the array you built look correct after it is filled in? – epascarello Commented May 8, 2018 at 16:32
  • It is the name of the column, is it wrong? @epascarello – MTT Commented May 8, 2018 at 16:32
  • The plete error is: Error: <rect> attribute y: Expected length, "NaN". o @ d3.v3.min.js:1 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 da.attr @ d3.v3.min.js:3 (anonymous) @ box.js:103 (anonymous) @ d3.v3.min.js:3 R @ d3.v3.min.js:1 da.each @ d3.v3.min.js:3 box @ box.js:19 da.call @ d3.v3.min.js:3 (anonymous) @ subject:262 (anonymous) @ d3.v3.min.js:1 t @ d3.v3.min.js:1 u @ d3.v3.min.js:1 load (async) St @ d3.v3.min.js:1 e @ d3.v3.min.js:3 (anonymous) @ subject:170 – MTT Commented May 8, 2018 at 16:35
  • Hi @epascarello thank you in advance! How can I know if the array looks correct? – MTT Commented May 8, 2018 at 16:37
 |  Show 4 more ments

1 Answer 1

Reset to default 3

The problem appears to be with passing the data to the boxplots:

// draw the boxplots    
svg.selectAll(".box")
    .data(data)
    .enter().append("g")
    .attr("transform", function(d) {
        return "translate(" + x(d[0]) + "," + margin.top + ")";
    })
    .call(chart.width(x.rangeBand()));

Your data array is an array of 2-element sub-arrays, where each sub-array consists of a column label and a column of data in a further sub-array. For example, data[2][0] is "Y3" but data[2][1] is the corresponding data for year Y3 ([0, 5, 5, 5, 8, ... ]).

D3 gets confused by this: it attempts to convert both values in the 2-element arrays to numbers, and of course converting the column sub-array to a single number fails and ends up with NaN.

What you need to do instead is to pass only an array of the column sub-arrays to .data(). Then, for the transform attribute, pass in the corresponding label into the x function. The function called in transform gets passed the index as well as the column of data: we use this index to get the corresponding label.

So, try replacing the lines above with the following lines:

// draw the boxplots    
svg.selectAll(".box")
    .data(data.map(function (d) { return d[1]; }))
    .enter().append("g")
    .attr("transform", function(d, i) {
        return "translate(" + x(data[i][0]) + "," + margin.top + ")";
    })
    .call(chart.width(x.rangeBand()));
发布评论

评论列表(0)

  1. 暂无评论