在D3 v4中套用nest()后,返回气泡图的模拟和半径值

时间:2018-11-07 04:39:54

标签: javascript d3.js

我在YouTube中引用了this video来制作气泡图。但是,作者没有使用嵌套函数对数据进行分组。使用nest()函数对数据进行预处理之后,我不知道如何将该值传递给代码中名为 radiusScale()的函数。我在想也许我应该传递

的值
d3.entries(groupByAgeAndtime)[i]["value"]

radiusScale()。 这是我遇到的问题的代码段。

var radiusScale = d3.scaleSqrt()
                        .domain([d3.min(Object.values(groupByAgeAndtime), function(d){
                              return d.mean_time_in_hospital;
                        }),d3.max(Object.values(groupByAgeAndtime), function(d){
                              return d.mean_time_in_hospital;
                        })])
                        .range([50,150]);

    for (i = 0; i < 10; i++)
    {
        console.log(d3.entries(groupByAgeAndtime)[i]["value"]);
    }

    var simulation = d3.forceSimulation()
    .force("x",d3.forceX(width/2).strength(0.05))
    .force("y",d3.forceY(height/2).strength(0.05))
    .force("collide", d3.forceCollide(function(d){
        return radiusScale(d.mean_time_in_hospital) + 2;
    }))

    var circles = svg.selectAll(".artist")
    .data(groupByAgeAndtime)
    .enter()
    .append("circle")
    .attr("class","artist")// the "artist" will transform into class name in HTML
    .attr("r", function(d){
        return radiusScale(Object.values(groupByAgeAndtime))
    })
    .attr("fill","lightblue")
    .on("click",function(d){
        console.log(d)
    })

这是屏幕截图:screenshot是我要传递给函数 radiusScale 的内容。我认为在传递正确的值后,圆圈将立即出现。如果没有,谁能告诉我要获得一个圆应该传递什么值?

这是我的js,html和.csv文件的JSFiddle。我真的很感谢能告诉我应该将什么值传递给该函数的人。

1 个答案:

答案 0 :(得分:0)

使用d3.nest()分组的数据groupByAgeAndtime必须用于仿真和圆图绘制。

请注意,您的radiusScale现在将获得正确的值,以映射到所选范围range([50, 150]);

var simulation = d3.forceSimulation()
  .force("x", d3.forceX(width / 2).strength(0.05))
  .force("y", d3.forceY(height / 2).strength(0.05))
  .force("collide", d3.forceCollide(function(d) {
    return radiusScale(d.mean_time_in_hospital);
  }))


simulation.nodes(Object.values(groupByAgeAndtime))
  .on('tick', ticked)

圆形相同,并且圆形半径现在与模拟半径匹配

var circles = svg.selectAll(".artist")
  .data(Object.values(groupByAgeAndtime))
  .enter()
  .append("circle")
  .attr("class", "artist")
  .attr("r", function(d) {
    return radiusScale(d.mean_time_in_hospital)
  })
  .attr("fill", "lightblue")
  .on("click", function(d) {
    console.log(d)
  })

这是功能示例,您的文本仍需要实现。 我已经将您的csv数据粘贴到了https://hastebin.com/raw/pasacimala

(function() {
  var width = 800,
    height = 350;

  var svg = d3.select("#chart")
    .append("svg")
    .attr("height", height)
    .attr("width", width)
    .attr("viewBox", `0 0 ${width} ${height}`)
   .attr("preserveAspectRatio","xMidYMid meet")
    .append("g")
    .attr("transform", "translate(0,0)");

  // import csv file
  d3.csv("https://cors-anywhere.herokuapp.com/https://hastebin.com/raw/pasacimala")
    .then(function(d) {
      //data preprocessing
      d.forEach(e => {
      	e.age = e.age.replace("[", "").replace(")", "");
      	e.time_in_hospital = + e.time_in_hospital;
			});
      return d; //must return something
    })
    .then((data, err) => ready(err, data))

  function ready(error, datapoints) {

    var groupByAgeAndtime = d3.nest()
      .key(function(d) {
        return d.age;
      })
      //.key(function(d) { return d.time_in_hospital; })
      .rollup(function(v) {
        return {
          mean_time_in_hospital: d3.mean(v, function(d) {
            return d.time_in_hospital;
          })
        }
      })
      .object(datapoints); //specify the dataset used



    /**************************************** SCALING PART **************************************************/

    var radiusScale = d3.scaleSqrt()
      .domain([d3.min(Object.values(groupByAgeAndtime), function(d) {
        return d.mean_time_in_hospital;
      }), d3.max(Object.values(groupByAgeAndtime), function(d) {
        return d.mean_time_in_hospital;
      })])
      .range([50, 150]);

 /*    for (i = 0; i < 10; i++) {
      //console.log(d3.entries(groupByAgeAndtime)[i]["key"]);
      console.log(d3.entries(groupByAgeAndtime)[i]["value"]);
    } */
	console.log(Object.values(groupByAgeAndtime))
    // STUCK HERE
    var simulation = d3.forceSimulation()
      .force("x", d3.forceX(width / 2).strength(0.05))
      .force("y", d3.forceY(height / 2).strength(0.05))
      .force("collide", d3.forceCollide(function(d) {
        return radiusScale(d.mean_time_in_hospital);
      }))

    // END OF STUCK HERE

    var circles = svg.selectAll(".artist")
      .data(Object.values(groupByAgeAndtime))
      .enter()
      .append("circle")
      .attr("class", "artist")
      .attr("r", function(d) {
        return radiusScale(d.mean_time_in_hospital)
      })
      .attr("fill", "lightblue")
      .on("click", function(d) {
        console.log(d)
      })

    // append = add something
    // text
    var texts = svg.selectAll('.text')
      .data(Object.keys(groupByAgeAndtime))
      .enter()
      .append('text')
      .text(e => e)
      .attr("text-anchor", "middle")
      .attr('color', 'black')
      .attr('font-size', '13')

    simulation.nodes(Object.values(groupByAgeAndtime))
      .on('tick', ticked)

    function ticked() {
      texts
        .attr("x", function(d) {
          return d.x
        })
        .attr("y", function(d) {
          return d.y
        })

      circles
        .attr("cx", function(d) {
          return d.x
        })
        .attr("cy", function(d) {
          return d.y
        })



    }
  }
})();
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="chart"></div>