使用nest()和汇总的Circle pack布局

时间:2015-04-02 15:58:55

标签: d3.js

我正在尝试使用nest().rollup创建圈组图。我收到以下错误:

Error: Invalid value for <g> attribute transform="translate(undefined,undefined)"
Error: Invalid value for <circle> attribute r="NaN"

我希望根据每个国家/地区的公司数量来确定圈子的大小。我正在尝试改编迈克博斯托克的Flare圈子包装示例。

如果有人能指出我的任何信息,我将非常感激。

JS代码:

var diameter = 960,
    format = d3.format(",d");

var pack = d3.layout.pack()
    .size([diameter - 4, diameter - 4])
    .value(function(d) { return d.size; });

var svg = d3.select("body").append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
  .append("g")
    .attr("transform", "translate(2,2)");

//Get data
d3.json("data/countriesNested.php", function(error, data){

  var submissionsByCountry = d3.nest()
      .key(function(d) { return d.Country; })
      .key(function(d) { return d.Organisation; })
      .rollup(function(leaves) { return leaves.length; })
      .entries(data);    

  var node = svg.datum(data).selectAll(".node")
      .data(pack.nodes)
    .enter().append("g")
      .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
      .attr("transform", function(d) { return "translate(" + d.cx + "," + d.cy + ")"; });

  node.append("title")
      .text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });

      node.append("circle")
          .attr("r", function(d) { return d.r; });

});

d3.select(self.frameElement).style("height", diameter + "px");

</script>

数据文件(使用PHP脚本从MySQL获得):

    [
  {
    "Country":"USA",
    "ID":4,
    "Organisation":"Company 1"
  },
  {
    "Country":"USA",
    "ID":5,
    "Organisation":"Company 2"
  },
  {
    "Country":"USA",
    "ID":6,
    "Organisation":"Company 3"
  },
 {
    "Country":"FRANCE",
    "ID":19,
    "Organisation":"Company 4"
  },
  {
    "Country":"FRANCE",
    "ID":24,
    "Organisation":"Company 5"
  },
  {
    "Country":"GERMANY",
    "ID":10,
    "Organisation":"Company 6"
  },
  {
    "Country":"ITALY",
    "ID":7,
    "Organisation":"Company 7"
  },
  .....

感谢阅读。

2 个答案:

答案 0 :(得分:4)

您的代码中有一些错误需要修复:

  1. 您需要为包布局上的子项和值设置访问器功能:

    var pack = d3.layout.pack()
      .size([diameter - 4, diameter - 4])
      .children(function(d) {
        return d.values;  // accessor for children
      })
      .value(function(d) {
        return d.values;  // accessor for values
      });
    
  2. 您的d3.nest()会返回一个数组,但d3.pack()要求您提供包含该层次结构的根对象。您必须创建一个根对象并将嵌套数组放在:

    var countryRoot = {
        key: "root",
        values: submissionsByCountry
    };
    
  3. 在您的代码中,您将数据嵌套到submissionsByCountry,但您没有在其他地方使用此变量。因此,在将数据绑定到svg时,您显然必须引用它。这是通过上面提到的根对象实现的,该对象稍后绑定到svg

    var node = svg.datum(countryRoot).selectAll(".node")
    
  4. 数据包布局添加到数据节点的属性包括值xy,而您将它们称为cxcy属性为<svg:circle>,但您的数据中不存在。因此,您收到了transform="translate(undefined,undefined)"错误消息。您应该使用这些属性:

    .attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });
    
  5. 我整理了一个有效的plunk

答案 1 :(得分:1)

那么,你想要一个父圆圈(让它称之为世界),子圆圈代表每个国家的大小,并且你的JSON数组中有一个条目数?

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

    var submissionsByCountry = d3.nest()
      .key(function(d) {
        return d.Country;
      })
      .rollup(function(leaves) {
        return leaves.length;
      })
      .entries(data);

    var root = {
      "key": "world",
      "children": submissionsByCountry
    };

    ...

这将为您提供与flare.json非常相似的内容。

接下来,您需要为d3指定适合您的圈子大小的accessor

var pack = d3.layout.pack()
  .size([diameter - 4, diameter - 4])
  .value(function(d) {
    return d.values; //<-- this comes from your roll-up and is the count.
  });

最后看起来您更改了示例代码以访问结果节点数据中不存在的cxcy属性:

var node = svg.datum(root).selectAll(".node")
  .data(pack.nodes)
  .enter().append("g")
  .attr("class", function(d) {
    return d.children ? "node" : "leaf node";
  })
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")"; //<-- this is .x, .y
  });

这里是example