嵌套折线图未显示

时间:2019-09-27 00:08:09

标签: javascript d3.js nested linechart

我遇到了出现嵌套折线图的问题。数据在控制台中,但是也许我缺少一些关键的东西。我正在关注以下内容以供参考:https://amber.rbind.io/2017/05/02/nesting/

可能我错误地调用了嵌套数据,或者可能需要将其附加到svg上?任何帮助,不胜感激!

图表需要在x轴上带有年份,在y轴上带有事件总和,并且每条线都应该是一个区域。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Nested Chart</title>
        <script src="../lib/d3.v5.min.js"></script>
        <style type="text/css">
            .pagebreak { page-break-before: always; }
            .axis path,
            .axis line {
                fill: none;
                stroke: black;
                shape-rendering: crispEdges;
            }
            .axis text {
                font-family: sans-serif;
                font-size: 11px;
            }
            .point {
                fill:none;
                size: 2px
            }
        </style>
    </head>

    <div style= "width:800px; margin:0 auto;" class ='body'></div>
    <div class="pagebreak"> </div>
    <body>

        <script type="text/javascript">

            var parseTime = d3.timeParse("%Y");


            var margin = {top: 20, right: 20, bottom: 30, left: 50},
                w = 960 - margin.left - margin.right,
                h = 500 - margin.top - margin.bottom;

            var padding =20;

 /////////////////get the data//////////////////               
            d3.csv("state-year-earthquakes.csv").then(function(dataset) {

            dataset.forEach(function(d) {
              d.date = parseTime(d.year);
              d.region  = d['region'];
              d.state = d['state'];
              d.count = d['count'];
              //console.log(d)
            });


/////////////////scales the data//////////////////
            var xScale = d3.scaleTime()
                .domain([d3.min(dataset,function (d) { return d.date }),d3.max(dataset,function (d) { return d.date }) ]).range([padding, w - padding * 2])

            var yScale = d3.scaleLinear()
                .domain([0, d3.max(dataset,function (d) { return d.count }) ]).range([h- padding, padding])    

            var xAxis = d3.axisBottom().scale(xScale);

            var yAxis = d3.axisLeft().scale(yScale);


/////////////////charts start here//////////////////

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


//Define the line
            var valueLine = d3.line()
                .x(function(d) { return xScale(d.date); })
                .y(function(d) { return yScale(+d.count); })


            var nest = d3.nest()
              .key(function(d){
                return d.region;
              })
                .key(function(d){
                return d.date;
              })
              .rollup(function(leaves){
                    return d3.sum(leaves, function(d) {return (d.count)});
                })
              .entries(dataset)


            var color = d3.scaleOrdinal(d3.schemeCategory10); // set the colour scale

             console.log(nest)


            var regYear = svg.selectAll(".regYear")
                .data(nest)
                .enter()
                .append("g")

            // console.log(regYear)

            var paths = regYear.selectAll(".line")
                .data(function(d){ 
                  return d.values 
                })
                .enter()
                .append("path");

            console.log(paths)
            // Draw the line
            paths
              .attr("d", function(d){
                return d.values
              })
              .attr("class", "line")


            svg.append("g").attr("class", "axis").attr("transform", "translate(0," + (h - padding) + ")").call(xAxis);       
            //draw Y axis
            svg.append("g").attr("class", "axis").attr("transform", "translate(" + padding + ",0)").call(yAxis);
            // add label
            svg.append("text").attr("x", (w/2)).attr("y", h+30).attr("text-anchor", "middle").text("Year");
            svg.append("text").attr("x", padding).attr("y", padding-20).attr("text-anchor", "middle").text("# of Events");            
            //add title
            svg.append("text").attr("x", (w/2)).attr("y", padding).attr("text-anchor", "middle").text("Events per Year by Category");   
            // add legend   
            var legend = svg.append("g")
            .attr("class", "legend")
            .attr("x", w - 65)
            .attr("y", 25)
            .attr("height", 100)
            .attr("width", 100);




////////////////////////////////////END///////////////////////////

            } );
        </script>

    </body>
</html>


data.csv

state,region,year,count
Alabama,South,2010,1
Alabama,South,2011,1
Alabama,South,2012,0
Alabama,South,2013,0
Alabama,South,2014,2
Alabama,South,2015,6
Alaska,West,2010,2245
Alaska,West,2011,1409
Alaska,West,2012,1166
Alaska,West,2013,1329
Alaska,West,2014,1296
Alaska,West,2015,1575
Connecticut,Northeast,2010,0
Connecticut,Northeast,2011,0
Connecticut,Northeast,2012,0
Connecticut,Northeast,2013,0
Connecticut,Northeast,2014,0
Connecticut,Northeast,2015,1
Missouri,Midwest,2010,2
Missouri,Midwest,2011,3
Missouri,Midwest,2012,2
Missouri,Midwest,2013,0
Missouri,Midwest,2014,1
Missouri,Midwest,2015,5

1 个答案:

答案 0 :(得分:2)

您有几个问题。首先,您没有使用线路生成器。应该是:

.attr("d", function(d) {
    return valueLine(d)
})

第二,您要解析日期字符串,然后再次将其转换为字符串。因此,更改您的行生成器(或不要将它们用作返回字符串的键):

var valueLine = d3.line()
    .x(function(d) {
        return xScale(new Date(d.key));
    })
    .y(function(d) {
        return yScale(d.value);
    })

最后,线生成器的每个基准必须是数组本身。所以:

var paths = regYear.selectAll(".line")
    .data(function(d) {
        return [d.values]
    })

这是您的代码,其中包含这些更改(以及一些用于路径的CSS):

path {
  fill: none;
  stroke: black;
}
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <title>Nested Chart</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <style type="text/css">
      .pagebreak {
        page-break-before: always;
      }

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

      .axis text {
        font-family: sans-serif;
        font-size: 11px;
      }

      .point {
        fill: none;
        size: 2px
      }

    </style>
  </head>

  <div style="width:800px; margin:0 auto;" class='body'></div>
  <div class="pagebreak"> </div>

  <body>

    <script type="text/javascript">
      var parseTime = d3.timeParse("%Y");


      var margin = {
          top: 20,
          right: 20,
          bottom: 30,
          left: 50
        },
        w = 960 - margin.left - margin.right,
        h = 500 - margin.top - margin.bottom;

      var padding = 20;

      /////////////////get the data//////////////////               
      const csv = `state,region,year,count
Alabama,South,2010,1
Alabama,South,2011,1
Alabama,South,2012,0
Alabama,South,2013,0
Alabama,South,2014,2
Alabama,South,2015,6
Alaska,West,2010,2245
Alaska,West,2011,1409
Alaska,West,2012,1166
Alaska,West,2013,1329
Alaska,West,2014,1296
Alaska,West,2015,1575
Connecticut,Northeast,2010,0
Connecticut,Northeast,2011,0
Connecticut,Northeast,2012,0
Connecticut,Northeast,2013,0
Connecticut,Northeast,2014,0
Connecticut,Northeast,2015,1
Missouri,Midwest,2010,2
Missouri,Midwest,2011,3
Missouri,Midwest,2012,2
Missouri,Midwest,2013,0
Missouri,Midwest,2014,1
Missouri,Midwest,2015,5`;

      const dataset = d3.csvParse(csv);

      dataset.forEach(function(d) {
        d.date = parseTime(d.year);
        d.region = d['region'];
        d.state = d['state'];
        d.count = d['count'];
        //console.log(d)
      });


      /////////////////scales the data//////////////////
      var xScale = d3.scaleTime()
        .domain([d3.min(dataset, function(d) {
          return d.date
        }), d3.max(dataset, function(d) {
          return d.date
        })]).range([padding, w - padding * 2])

      var yScale = d3.scaleLinear()
        .domain([0, d3.max(dataset, function(d) {
          return d.count
        })]).range([h - padding, padding])

      var xAxis = d3.axisBottom().scale(xScale);

      var yAxis = d3.axisLeft().scale(yScale);


      /////////////////charts start here//////////////////

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


      //Define the line
      var valueLine = d3.line()
        .x(function(d) {
          return xScale(new Date(d.key));
        })
        .y(function(d) {
          return yScale(d.value);
        })


      var nest = d3.nest()
        .key(function(d) {
          return d.region;
        })
        .key(function(d) {
          return d.date;
        })
        .rollup(function(leaves) {
          return d3.sum(leaves, function(d) {
            return (d.count)
          });
        })
        .entries(dataset)


      var color = d3.scaleOrdinal(d3.schemeCategory10); // set the colour scale


      var regYear = svg.selectAll(".regYear")
        .data(nest)
        .enter()
        .append("g")

      // console.log(regYear)

      var paths = regYear.selectAll(".line")
        .data(function(d) {
          return [d.values]
        })
        .enter()
        .append("path");

      // Draw the line
      paths
        .attr("d", function(d) {
          return valueLine(d)
        })
        .attr("class", "line")


      svg.append("g").attr("class", "axis").attr("transform", "translate(0," + (h - padding) + ")").call(xAxis);
      //draw Y axis
      svg.append("g").attr("class", "axis").attr("transform", "translate(" + padding + ",0)").call(yAxis);
      // add label
      svg.append("text").attr("x", (w / 2)).attr("y", h + 30).attr("text-anchor", "middle").text("Year");
      svg.append("text").attr("x", padding).attr("y", padding - 20).attr("text-anchor", "middle").text("# of Events");
      //add title
      svg.append("text").attr("x", (w / 2)).attr("y", padding).attr("text-anchor", "middle").text("Events per Year by Category");
      // add legend   
      var legend = svg.append("g")
        .attr("class", "legend")
        .attr("x", w - 65)
        .attr("y", 25)
        .attr("height", 100)
        .attr("width", 100);




      ////////////////////////////////////END///////////////////////////

    </script>

  </body>

</html>