D3.js 多个部队网络聚集在各个地点周围

D3.js 多个部队网络聚集在各个地点周围,d3.js,force-layout,D3.js,Force Layout,我正在构建一个可视化系统,试图在研讨会上展示各学科之间的合作。共有七个位置,我希望每个位置都是涉及的任何规程的中心节点——一种类似于这样的“辐射”模式,最终将被映射: 我已经在网络建设方面取得了一些进展,我一直在博斯托克寻找一些灵感。但我还是有点卡住了 网络如下所示: var width = 1200, height = 650; var color = d3.scale.category20(); d3.csv("./d/network.csv", function(error,

我正在构建一个可视化系统,试图在研讨会上展示各学科之间的合作。共有七个位置,我希望每个位置都是涉及的任何规程的中心节点——一种类似于这样的“辐射”模式,最终将被映射:

我已经在网络建设方面取得了一些进展,我一直在博斯托克寻找一些灵感。但我还是有点卡住了

网络如下所示:

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);
  }
});
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"
这给了我完整的网络:

但现在我关注的是分离的独立网络,例如,尽管完整的网络图显示斯坦福和剑桥共享“化学”,但我希望斯坦福和剑桥单独出现,每个都有一个不共享的“化学”节点。数据如下所示:

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

我想,我的问题可以归结为:我应该遍历数据以找到
source
target
的唯一匹配项,还是
d3.nest
是我的朋友?我该如何开始这样做呢?

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

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

在我看来,你可能想在D3之外做一些预处理。特别是,在其上运行其他一些图形布局算法可能会很有用,以获得节点位置的合理默认值——在您的图片中,所有这些看起来都有点杂乱,而force布局在缓解这一问题方面并不特别好。