D3多线图问题

时间:2022-01-11 20:31:57

Hello I am trying to build a multi-line chart that displays rates for each month year over year. I am getting a "TypeError: t is undefined" error in the console and while I can see the x and y axis populated, no lines are appearing in the chart. Any help appreciated!

您好我正在尝试构建一个多行图表,显示每个月的年度费率。我在控制台中收到“TypeError:t is undefined”错误,虽然我可以看到填充了x和y轴,但图表中没有出现任何行。任何帮助赞赏!

The HTML file code is here:

HTML文件代码在这里:

 <!DOCTYPE html>
 <meta charset="utf-8">
 <style>

 body {
   font: 10px sans-serif;
 }

 .axis path,
 .axis line {
   fill: none;
   stroke: #000;
   shape-rendering: crispEdges;
 }

 .x.axis path {
   display: none;
 }

 .line {
   fill: none;
   stroke: steelblue;
   stroke-width: 1.5px;
 }

 </style>
 <body>
 <script src="//d3js.org/d3.v3.min.js"></script>
 <script>

 var margin = {top: 20, right: 80, bottom: 30, left: 50},
     width = 960 - margin.left - margin.right,
     height = 500 - margin.top - margin.bottom;


 var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);

 var y = d3.scale.linear().range([height, 0]);

 var color = d3.scale.ordinal().range(["#666666", "#262626", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

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

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

 var line = d3.svg.line().interpolate("basis").x(function(d) { return x(d.date); }).y(function(d) { return y(d.value); });

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

 d3.json("yoy_values.json", function(error, data) {
   if (error) throw error;

   var myValues = d3.keys(data[0]).filter(function(key) { return key !== "date"; });

     data.forEach(function(d) {
        d.rates = myValues.map(function(name) { return {name: name, value: +d[name]}; });
        console.log(d.rates);

     });

   x.domain(data.map(function(d) { return d.date; }));


 y.domain([
     d3.min(data,   function(d) { return d3.min(d.rates, function(d) { return d.value; }); }),
     d3.max(data,   function(d) { return d3.max(d.rates, function(d) { return d.value; }); })
     ]);

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

   svg.append("g")
       .attr("class", "y axis")
       .call(yAxis)
     .append("text")
       .attr("transform", "rotate(-90)")
       .attr("y", 6)
       .attr("dy", ".71em")
       .style("text-anchor", "end")
       .text("Rates");

   var state = svg.selectAll(".state")
       .data(myValues.slice().reverse())
     .enter().append("g")
       .attr("class", "state")
       .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

   state.append("path")
       .attr("class", "line")
       .attr("d", function(d) { return line(d.rates); })
       .style("stroke", function(d) { return color(d.name); });

   state.append("text")
       .datum(function(d) { return {name: d.name, value: d.rates[d.rates.length - 1]}; })
       .attr("transform", function(d) { return "translate(" + x(d.value) + "," + y(d.name) + ")"; })
       .attr("x", 3)
       .attr("dy", ".35em")
       .text(function(d) { return d.name; });
 });

 </script>

The JSON file I am reading looks like this:

我正在阅读的JSON文件如下所示:

[
    {"date":"Jan","2014":"0.0812","2015":"0.0780","2016":"0.0838"},
    {"date":"Feb","2014":"0.0806","2015":"0.0768","2016":"0.0893"},
    {"date":"Mar","2014":"0.0858","2015":"0.0847","2016":null},
    {"date":"Apr","2014":"0.0848","2015":"0.0889","2016":null},
    {"date":"May","2014":"0.0890","2015":"0.0890","2016":null},
    {"date":"Jun","2014":"0.0928","2015":"0.0865","2016":null},
    {"date":"Jul","2014":"0.0857","2015":"0.0799","2016":null},
    {"date":"Aug","2014":"0.0905","2015":"0.0845","2016":null},
    {"date":"Sep","2014":"0.1003","2015":"0.0934","2016":null},
    {"date":"Oct","2014":"0.0971","2015":"0.0993","2016":null},
    {"date":"Nov","2014":"0.0912","2015":"0.0973","2016":null},
    {"date":"Dec","2014":"0.0800","2015":"0.0777","2016":null}
]

1 个解决方案

#1


0  

It's hard to tell from just code eyeballing, but I noticed:

只是代码眼球很难说,但我注意到:

  1. You make a series of .rates properties from the non-"date" json data, so .rates for the first datum would be [{name:"2014", value:"0.0812"},{name:"2015", value:"0.0780"},{name:"2016", value:"0.0838"}]

    您从非“日期”json数据中生成一系列.rates属性,因此第一个数据的.rates将是[{name:“2014”,value:“0.0812”},{name:“2015”,value :“0.0780”},{name:“2016”,value:“0.0838”}]

    d.rates = myValues.map(function(name) { return {name: name, value: +d[name]}; });

    d.rates = myValues.map(function(name){return {name:name,value:+ d [name]};});

  2. You then pass these to a d3.svg.line function

    然后将它们传递给d3.svg.line函数

    .attr("d", function(d) { return line(d.rates); })

    .attr(“d”,function(d){return line(d.rates);})

  3. But this line function has been previously set up to seemingly expect .date and .value properties not .name and .value

    但是这个行函数之前已经被设置为看起来期望.date和.value属性不是.name和.value

    var line = d3.svg.line().interpolate("basis").x(function(d) { return x(d.date); }).y(function(d) { return y(d.value); });

    var line = d3.svg.line()。interpolate(“basis”)。x(function(d){return x(d.date);})。y(function(d){return y(d.value) ;});

  4. And the scale x has been set up to expect .date (the month strings) as arguments, because they were set as the domain

    并且缩放x已经设置为期望.date(月份字符串)作为参数,因为它们被设置为域

    x.domain(data.map(function(d) { return d.date; }));

    x.domain(data.map(function(d){return d.date;}));

In short, it seems the x scale and line function are expecting data objects categorised by month to draw one line per year, but you're passing in the .rates objects which are organised by year in the expectation of drawing one line per month?

简而言之,x scale和line函数似乎期望按月分类的数据对象每年绘制一行,但是你传入的.rates对象是按年份组织的,期望每月绘制一行?

#1


0  

It's hard to tell from just code eyeballing, but I noticed:

只是代码眼球很难说,但我注意到:

  1. You make a series of .rates properties from the non-"date" json data, so .rates for the first datum would be [{name:"2014", value:"0.0812"},{name:"2015", value:"0.0780"},{name:"2016", value:"0.0838"}]

    您从非“日期”json数据中生成一系列.rates属性,因此第一个数据的.rates将是[{name:“2014”,value:“0.0812”},{name:“2015”,value :“0.0780”},{name:“2016”,value:“0.0838”}]

    d.rates = myValues.map(function(name) { return {name: name, value: +d[name]}; });

    d.rates = myValues.map(function(name){return {name:name,value:+ d [name]};});

  2. You then pass these to a d3.svg.line function

    然后将它们传递给d3.svg.line函数

    .attr("d", function(d) { return line(d.rates); })

    .attr(“d”,function(d){return line(d.rates);})

  3. But this line function has been previously set up to seemingly expect .date and .value properties not .name and .value

    但是这个行函数之前已经被设置为看起来期望.date和.value属性不是.name和.value

    var line = d3.svg.line().interpolate("basis").x(function(d) { return x(d.date); }).y(function(d) { return y(d.value); });

    var line = d3.svg.line()。interpolate(“basis”)。x(function(d){return x(d.date);})。y(function(d){return y(d.value) ;});

  4. And the scale x has been set up to expect .date (the month strings) as arguments, because they were set as the domain

    并且缩放x已经设置为期望.date(月份字符串)作为参数,因为它们被设置为域

    x.domain(data.map(function(d) { return d.date; }));

    x.domain(data.map(function(d){return d.date;}));

In short, it seems the x scale and line function are expecting data objects categorised by month to draw one line per year, but you're passing in the .rates objects which are organised by year in the expectation of drawing one line per month?

简而言之,x scale和line函数似乎期望按月分类的数据对象每年绘制一行,但是你传入的.rates对象是按年份组织的,期望每月绘制一行?