简体   繁体   中英

d3 heatmap using nested json data: how to create grids

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"); 

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM