d3 heatmap using nested json data: how to create grids

笑着哭i 提交于 2020-01-06 06:56:28

问题


Referring to this example here: http://bl.ocks.org/tjdecke/5558084

I would like to create a heatmap of 52 rows, and 7 columns. 52 rows represents the 52 weeks of a year, and 7 column represents 7 days of a week.

With a dataset like this: (posting abbreviated version below). "days" signify the 7 days of a week, the numbers inside signify number of activity within a day. "total" signifies total number of activity in a week. "week" seems to be a timestamp of sorts.

However, I am having difficulty figuring out how to create the grids, as the example dataset uses d.day with 7 values and d.hour with 24 values to create the grid. Specifically, what should i be doing with the days array?

I am not sure on how to process the json values as well, as in, how should i be defining my variables to work with this dataset.

[
  {
    "days": [
      0,
      0,
      0,
      0,
      0,
      1,
      0
    ],
    "total": 1,
    "week": 1457827200
  },
  {
    "days": [
      0,
      0,
      0,
      1,
      0,
      3,
      1
    ],
    "total": 5,
    "week": 1458432000
  },
  {
    "days": [
      1,
      0,
      0,
      1,
      5,
      0,
      1
    ],
    "total": 8,
    "week": 1459036800
  },
  {
    "days": [
      0,
      0,
      0,
      2,
      0,
      1,
      1
    ],
    "total": 4,
    "week": 1459641600
  },
  {
    "days": [
      0,
      1,
      3,
      0,
      2,
      0,
      0
    ],
    "total": 6,
    "week": 1460246400
  },
  {
    "days": [
      0,
      1,
      1,
      2,
      2,
      0,
      0
    ],
    "total": 6,
    "week": 1460851200
  },
  {
    "days": [
      1,
      0,
      3,
      0,
      2,
      1,
      0
    ],
    "total": 7,
    "week": 1461456000
  },
  {
    "days": [
      0,
      0,
      0,
      0,
      0,
      0,
      0
    ],
    "total": 0,
    "week": 1462060800
  }
  ]

    d3.json("/data/frequency.json", function (error, data) {

       // NOT SURE, PROBABLY WRONG
      data.forEach(function(d) {
        ddays = +d.days;
        total = +d.total;
        week = +d.week;
      });


      // define range!!!
      var x = d3.scaleLinear().domain([0, data.length]).range([0, width]);

      //52 weeks
      var y = d3.scaleLinear()
      .domain([0, 52])
      .rangeRound([height, 0]);

      // Generate rectangle for each json object
      var rectangles = svg.selectAll('rect')
      .data(data)
      .enter()
      .append('rect')
      .attr("x", function(d, index) {
        return x(index); }) //WRONG!!
      .attr("y", function(d, index) {
        return y; }) // WRONG!!
      .attr("width", gridSize)
      .attr("height", gridSize)
      .style("fill", 'black')
      .attr("class", "bordered");

回答1:


with your nested data, you could first append group elements per object to create a "row" in your grid for each week, which get their y coordinate based on their index.

Then for each row, append rects based on the days array within object.

The trick is to do two data() joins, with the second join accessing the days array from within the already joined data.

For example:

     let data = [
  {
    "days": [
      0,
      0,
      0,
      0,
      0,
      1,
      0
    ],
    "total": 1,
    "week": 1457827200
  },
  {
    "days": [
      0,
      0,
      0,
      1,
      0,
      3,
      1
    ],
    "total": 5,
    "week": 1458432000
  },
  {
    "days": [
      1,
      0,
      0,
      1,
      5,
      0,
      1
    ],
    "total": 8,
    "week": 1459036800
  },
  {
    "days": [
      0,
      0,
      0,
      2,
      0,
      1,
      1
    ],
    "total": 4,
    "week": 1459641600
  },
  {
    "days": [
      0,
      1,
      3,
      0,
      2,
      0,
      0
    ],
    "total": 6,
    "week": 1460246400
  },
  {
    "days": [
      0,
      1,
      1,
      2,
      2,
      0,
      0
    ],
    "total": 6,
    "week": 1460851200
  },
  {
    "days": [
      1,
      0,
      3,
      0,
      2,
      1,
      0
    ],
    "total": 7,
    "week": 1461456000
  },
  {
    "days": [
      0,
      0,
      0,
      0,
      0,
      0,
      0
    ],
    "total": 0,
    "week": 1462060800
  }
  ]
 
			let gridSize = 20;
      let width = (gridSize + 1) * 7; 
    	let height = (gridSize + 1) * data.length;
    	
      // define range!!!
      var x = d3.scaleLinear()
      .domain([0, 7])
      .range([0, width]);

      //52 weeks
      var y = d3.scaleLinear()
      .domain([0, data.length])
      .rangeRound([height, 0]);
    
    	let svg = d3.select("body").append("svg")
      	.attr("width", width)
      .attr("height", height)

      // Generate rows for each json object
      var rows = svg.selectAll('.row')
      .data(data)
      .enter()
      .append('g')
      .attr("transform", function(d, i){ 
      	return "translate(0," + y(i) + ")"
      })
      
      // Generate rects for the array of days per object
      let box = rows.selectAll("rect")
      	.data(function(d){ return d.days })
      	.enter()
      	.append("rect")
				.attr("x", function(d, i) { return x(i); }) 
        .attr("width", gridSize)
        .attr("height", gridSize)
        .style("fill", 'black')
        .attr("class", "bordered");
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
</body>


来源:https://stackoverflow.com/questions/46916634/d3-heatmap-using-nested-json-data-how-to-create-grids

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!