D3 v5:多折线图,无法绘制多条线

时间:2020-05-05 18:15:25

标签: d3.js

谢谢您可以提供的任何帮助,我是D3的新手,并且在跟随我在网上看到的多线图示例很困难。我的数据看起来像:

country,year,average
United States,1970,51
United States,1971,50
United States,1972,54
United States,1973,56
United States,1974,53
United States,1975,57
United States,1976,60
Brazil,1970,23
Brazil,1971,25
Brazil,1972,24
Brazil,1973,21
Brazil,1974,25
Brazil,1975,26
Brazil,1976,24

针对多个国家/地区,我想为每个国家/地区设置一行。

var margin = {top: 10, right: 40, bottom: 150, left: 70},
width = 760 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom; 

 var w = width + margin.left + margin.right;
 var h = height + margin.top + margin.bottom;

 var svg = d3.select("body").append("svg") // this appends a new SVG element to body
    .attr("width", w) // set the width 
    .attr("height", h) // set the height
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// x scale will handle time
 var xScale = d3.scaleBand().range([0, width]).padding(0.1);

// y scale will handle energy consumption values
 var yScale = d3.scaleLinear().range([height,0]);

// Define X and Y AXIS
 var yAxis = d3.axisLeft(yScale).ticks(5);
 var xAxis = d3.axisBottom(xScale); 

 function rowConverter(data) {
      return {
           country : data.country, 
           year : +data.year,
           average : +data.average // the + operator parses strings into numbers
      };
}

// line generator function
 var line = d3.line()
    .curve(d3.curveBasis)
    .x(function(d) { return xScale(d.year); })
    .y(function(d) { return yScale(d.average); })

d3.csv("EvenMore.csv", rowConverter).then(function(data) {

     var countries = d3.nest()
        .key(function (d) { return d.country; })
        .entries(data); 

     console.log(countries);

     yScale.domain([0,d3.max(data, function(d) {return d.average; } )]); 
     xScale.domain(d3.extent(data, function(d) { return d.year; } )); 

    // Draw xAxis
     svg.append("g") // add a new svg group element
        .attr("class", "x axis")
        .attr("transform", "translate(0, " + height + ")")
        .call(xAxis)
        .selectAll("text")
        .attr("dx", "-.8em")
        .attr("dy", ".25em")
        .attr("text-anchor", "end");

    // Draw yAxis
     svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .selectAll("text")
        .attr("dx", "-.8em")
        .attr("dy", ".25em")
        .attr("text-anchor", "end");


    svg.selectAll("path")
         .data(countries)
        .enter()
        .append("path")
        .attr("class", "line")
        .attr("d", function(d) { 
             return line(d.values); 
        });

}); 

我不知道这些错误是什么意思,错误:属性d:期望的数字,“ .... 33333333333334LNaN,114.27777777…”:

Error: <path> attribute d: Expected number, "….33333333333334LNaN,114.27777777…"

1 个答案:

答案 0 :(得分:2)

问题

您没有正确使用带刻度。带标度不是定量标度,因此没有上限和下限。相反,需要指定域的每个值:

domain中的第一个元素将映射到第一个波段,即 第二个域的值到第二个带,依此类推。域值是 从字符串值到索引内部存储在映射中;的 然后,使用所得的索引来确定频段(docs

这说明了您的错误,您已经为域指定了两个值,第一年和最后一年。我们可以看到,在查看刻度时,域仅是这两个值的一种方式(默认情况下,带刻度的轴包括所有刻度线,但是即使在这里,如果1970和1976是开始和结束,间隔实际上也很奇怪。值):

enter image description here

错误消息还有助于发现错误:如果第一个坐标的x值为NaN,则在检查路径"Expected Number, "MNan,1234..."属性时(尤其是未应用任何曲线),该消息将读取d。查看除第一个和最后一个都是NaN之外的每个坐标的x值。

解决方案

您需要提供规模域中的所有值。我们可以通过以下方式获取所有值:

xScale.domain(data.map(function(d) { return d.year; }))

设置域时,天平将清除重复项。

var margin = {top: 10, right: 40, bottom: 150, left: 70},
width = 760 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom; 

 var w = width + margin.left + margin.right;
 var h = height + margin.top + margin.bottom;

 var svg = d3.select("body").append("svg") // this appends a new SVG element to body
    .attr("width", w) // set the width 
    .attr("height", h) // set the height
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// x scale will handle time
 var xScale = d3.scaleBand().range([0, width]).padding(0.1);

// y scale will handle energy consumption values
 var yScale = d3.scaleLinear().range([height,0]);

// Define X and Y AXIS
 var yAxis = d3.axisLeft(yScale).ticks(5);
 var xAxis = d3.axisBottom(xScale); 

 function rowConverter(data) {
      return {
           country : data.country, 
           year : +data.year,
           average : +data.average // the + operator parses strings into numbers
      };
}

// line generator function
 var line = d3.line()
    .curve(d3.curveBasis)
    .x(function(d) { return xScale(d.year); })
    .y(function(d) { return yScale(d.average); })

var data = d3.csvParse(d3.select("pre").remove().text())


    data = data.map(rowConverter);

     var countries = d3.nest()
        .key(function (d) { return d.country; })
        .entries(data); 

     yScale.domain([0,d3.max(data, function(d) {return d.average; } )]); 
     xScale.domain(countries[0].values.map(function(d) { return d.year; })); 

    // Draw xAxis
     svg.append("g") // add a new svg group element
        .attr("class", "x axis")
        .attr("transform", "translate(0, " + height + ")")
        .call(xAxis)
        .selectAll("text")
        .attr("dx", "-.8em")
        .attr("dy", ".25em")
        .attr("text-anchor", "end");

    // Draw yAxis
     svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .selectAll("text")
        .attr("dx", "-.8em")
        .attr("dy", ".25em")
        .attr("text-anchor", "end");


    svg.selectAll(null)
        .data(countries)
        .enter()
        .append("path")
        .attr("class", "line")
        .attr("d", function(d) {
             return line(d.values); 
        });
.line {
    stroke-width: 2px;
    fill: none;
    stroke:black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<pre>country,year,average
United States,1970,51
United States,1971,50
United States,1972,54
United States,1973,56
United States,1974,53
United States,1975,57
United States,1976,60
Brazil,1970,23
Brazil,1971,25
Brazil,1972,24
Brazil,1973,21
Brazil,1974,25
Brazil,1975,26
Brazil,1976,24</pre>