多个力量网络聚集在各个位置

时间:2013-11-25 20:57:28

标签: d3.js force-layout

我正在构建一个可视化,旨在展示研讨会中学术界的合作。有七个位置,我希望每个位置都是所涉及的任何学科的中心节点 - 这样的一种“辐条”模式,最终将被映射:

Network

我已经在构建网络的过程中占了一席之地,而且我一直在寻找Bostock的Force Layout Multiples以获得灵感。但我还是有点卡住了。

网络看起来像这样:

var width = 1200,
    height = 650;

var color = d3.scale.category20();

d3.csv("./d/network.csv", function(error, csv_data) {

  // array of nodes
  var nodes = {};

  // compute nodes from links
  csv_data.forEach(function(link) {
      link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
      link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
  });

  var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(csv_data)
    .size([width, height])
    .linkDistance(60)
    .charge(-900)
    .on("tick", tick)
    .start();

  var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

  // add the edges
  var path = svg.append("g").selectAll("path")
    .data(force.links())
  .enter().append("path")
    .attr("class", "link");

  // define the nodes
  var node = svg.selectAll(".node")
    .data(force.nodes())
  .enter().append("g")
    .attr("class", "node")
    .on("mouseover", mouseover)
    .on("mouseout", mouseout)
    .call(force.drag);

  // add the nodes
  node.append("circle")
    .attr("r", 5)
    .style("fill", function(d) { console.log('d: ', d); return color(d.name); });

  // add the text 
  node.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name; });

  // ========================== Functions ==========================

  // add the edges
  function tick() {
    path.attr("d", function(d) {
        var dx = d.target.x - d.source.x,
            dy = d.target.y - d.source.y,
            dr = Math.sqrt(dx * dx + dy * dy);
        return "M" + 
            d.source.x + "," + 
            d.source.y + "A" + 
            dr + "," + dr + " 0 0,1 " + 
            d.target.x + "," + 
            d.target.y;
    });

    node
        .attr("transform", function(d) { 
            return "translate(" + d.x + "," + d.y + ")"; });
  }

  // resize nodes on mouseover and mouseout
  function mouseover() {
    d3.select(this).select("circle").transition()
        .duration(750)
        .attr("r", 8);
  }  
  function mouseout() {
    d3.select(this).select("circle").transition()
        .duration(750)
        .attr("r", 5);
  }
});

这给了我完整的网络:

Full network

但是现在我正在分离和独立的网络,所以例如虽然完整的网络图显示斯坦福和剑桥分享“化学”,但我希望斯坦福和剑桥独立出现,每个人都有一个“化学”节点那是不共享的。数据看起来像这样:

source,target
"Berlin","Architecture and Urban Planning"
"Berlin","Human-Computer Interaction"
"Berlin","Informatics"
"Berlin","Sociology"
"Berlin","Sociology and Social Policy"
"Berlin","Informatics"
"Berlin","Industrial Design"
"Berlin","Engineering"
"Brussels","Medicine"
"Brussels","Sociology"
"Brussels","Engineering"
"Brussels","Genetics"
"Brussels","Science, Technology, and Society"
"Brussels","Urban Planning"
"Brussels","Gender and Neuroscience"
"Brussels","Informatics"
"Cambridge","Computer Science"
"Cambridge","Physics"
"Cambridge","Physics"
"Cambridge","Computer Science"
"Cambridge","Google Research"
"Cambridge","Linguistics"
"Cambridge","Pharmacology"
"Cambridge","History of Science"
"Cambridge","Biology"
"Cambridge","Computer Science"
"Cambridge","Neurobiology"
"Cambridge","Chemistry"

我的问题,我认为,归结为:我应该遍历数据以查找sourcetarget的唯一匹配项,还是我的朋友d3.nest?我怎么可能开始这样做?

1 个答案:

答案 0 :(得分:2)

您按照规则(即nodes[link.target] = ...)索引节点的方式可确保唯一性,但实际上最终会在整个网络中创建过多的唯一性。换句话说,只有一个“信息学”节点,并且最终连接到它出现的所有城市。相反,您需要确保每个城市的唯一性:

var key = link.target + '@' + link.source;
link.target = nodes[key] || (nodes[key] = {name: link.target});