【问题标题】:d3 heatmap using nested json data: how to create grids使用嵌套 json 数据的 d3 热图:如何创建网格
【发布时间】:2017-10-24 17:31:07
【问题描述】:

在此处参考此示例:http://bl.ocks.org/tjdecke/5558084

我想创建一个 52 行 7 列的热图。 52 行代表一年中的 52 周,7 列代表一周中的 7 天。

使用这样的数据集:(在下面发布缩写版本)。 “days”表示一周的7天,里面的数字表示一天内的活动数。 “total”表示一周内的活动总数。 “周”似乎是某种时间戳。

但是,我很难弄清楚如何创建网格,因为示例数据集使用具有 7 个值的 d.day 和具有 24 个值的 d.hour 来创建网格。具体来说,我应该如何处理 days 数组?

我也不确定如何处理 json 值,例如,我应该如何定义变量以使用此数据集。

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

【问题讨论】:

    标签: javascript json d3.js


    【解决方案1】:

    使用您的嵌套数据,您可以首先为每个对象附加组元素,以便每周在网格中创建一个“行”,根据其索引获取它们的 y 坐标。

    然后对于每一行,根据对象内的天数组附加矩形。

    诀窍是进行两次 data() 连接,第二次连接从已连接的数据中访问 days 数组。

    例如:

         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>

    【讨论】:

    • 感谢您的建议! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 2021-04-15
    相关资源
    最近更新 更多