破碎的D3js和弦图

时间:2017-02-25 19:19:10

标签: d3.js chord-diagram

我在使用D3和弦图时遇到了问题。

https://jsfiddle.net/Nyquist212/3vc0f2e5/6/

它使用了Steve Halls出色的Chord Mapper功能。

http://www.delimited.io/blog/2013/12/8/chord-diagrams-in-d3

虽然我过去取得了成功,但我收到此错误表明我的数据存在问题(?)。

  

错误:属性d:预期数字," ... 666666669 0 1,1   NaN时,NaNLNaN,NANA ..."

有人可以帮助我理解我可能做错了吗?

var data = [
  {
    "count": 1,
    "source": "6540",
    "target": "1030"
  },
  {
    "count": 1,
    "source": "6263",
    "target": "727"
  },
  {
    "count": 1,
    "source": "16760",
    "target": "3085"
  },
  {
    "count": 1,
    "source": "7518",
    "target": "2035"
  },
  {
    "count": 1,
    "source": "5512",
    "target": "1560"
  },
  {
    "count": 1,
    "source": "16239",
    "target": "3135"
  },
  {
    "count": 1,
    "source": "116528",
    "target": "4130"
  },
  {
    "count": 1,
    "source": "14060M",
    "target": "3130"
  },
  {
    "count": 1,
    "source": "6264",
    "target": "727"
  },
  {
    "count": 1,
    "source": "6265",
    "target": "727"
  },
  {
    "count": 1,
    "source": "6542",
    "target": "1036"
  },
  {
    "count": 1,
    "source": "16018",
    "target": "3035"
  },
  {
    "count": 1,
    "source": "116619LB",
    "target": "3135"
  },
  {
    "count": 1,
    "source": "116400",
    "target": "3130"
  },
  {
    "count": 1,
    "source": "5501",
    "target": "1530"
  },
  {
    "count": 1,
    "source": "6542",
    "target": "1065"
  },
  {
    "count": 1,
    "source": "1016",
    "target": "1560"
  },
  {
    "count": 1,
    "source": "6262",
    "target": "727"
  },
  {
    "count": 1,
    "source": "16520",
    "target": "4030"
  },
  {
    "count": 1,
    "source": "6517",
    "target": "1166"
  },
  {
    "count": 1,
    "source": "16528",
    "target": "4030"
  },
  {
    "count": 1,
    "source": "116518",
    "target": "4130"
  },
  {
    "count": 1,
    "source": "5514",
    "target": "1520"
  },
  {
    "count": 1,
    "source": "6827",
    "target": "2035"
  },
  {
    "count": 1,
    "source": "5508",
    "target": "1530"
  },
  {
    "count": 1,
    "source": "16515",
    "target": "4030"
  },
  {
    "count": 1,
    "source": "5510",
    "target": "1530"
  },
  {
    "count": 1,
    "source": "114234",
    "target": "2235"
  },
  {
    "count": 1,
    "source": "16238",
    "target": "3135"
  },
  {
    "count": 1,
    "source": "5517",
    "target": "1520"
  },
  {
    "count": 1,
    "source": "1675",
    "target": "1565"
  },
  {
    "count": 1,
    "source": "14000",
    "target": "3000"
  },
  {
    "count": 1,
    "source": "1804",
    "target": "1556"
  },
  {
    "count": 1,
    "source": "114200",
    "target": "2235"
  },
  {
    "count": 1,
    "source": "16713",
    "target": "3185"
  },
  {
    "count": 1,
    "source": "1675",
    "target": "1575"
  },
  {
    "count": 1,
    "source": "116589",
    "target": "4130"
  },
  {
    "count": 1,
    "source": "6917",
    "target": "2035"
  },
  {
    "count": 1,
    "source": "1678",
    "target": "1565"
  },
  {
    "count": 1,
    "source": "16250",
    "target": "3135"
  },
  {
    "count": 1,
    "source": "6916",
    "target": "2035"
  },
  {
    "count": 1,
    "source": "6538A",
    "target": "1030"
  },
  {
    "count": 1,
    "source": "6604",
    "target": "1065"
  },
  {
    "count": 1,
    "source": "16750",
    "target": "3075"
  },
  {
    "count": 1,
    "source": "16000",
    "target": "3035"
  },
  {
    "count": 1,
    "source": "16014",
    "target": "3035"
  },
  {
    "count": 1,
    "source": "16700",
    "target": "3175"
  },
  {
    "count": 1,
    "source": "16550",
    "target": "3085"
  },
  {
    "count": 1,
    "source": "1655",
    "target": "1575"
  },
  {
    "count": 1,
    "source": "116523",
    "target": "4130"
  },
  {
    "count": 1,
    "source": "116598",
    "target": "4130"
  },
  {
    "count": 1,
    "source": "6824",
    "target": "2035"
  },
  {
    "count": 1,
    "source": "6610",
    "target": "1030"
  },
  {
    "count": 1,
    "source": "6241",
    "target": "645"
  },
  {
    "count": 1,
    "source": "16518",
    "target": "4030"
  },
  {
    "count": 1,
    "source": "16523",
    "target": "4030"
  },
  {
    "count": 1,
    "source": "1803",
    "target": "1556"
  },
  {
    "count": 1,
    "source": "1673",
    "target": "1575"
  }
];

var mpr = chordMpr(data);

    mpr
    .addValuesToMap('source')
    .setFilter(function (row, a, b) {
        return(row.source == a.name && row.target == b.name);
        })
    .setAccessor(function (recs, a, b) {
        if(!recs[0]) return 0;
        return +recs[0].count ;
        });

    drawChords(mpr.getMatrix(), mpr.getMap());

function drawChords (matrix, mmap) {

        var w = 950, h = 950, r1 = h / 3, r0 = r1 - 150;

        var fill = d3.scale.category20();

        var chord = d3.layout.chord()
            .padding(.02)   // Padding between arc categories
            .sortSubgroups(d3.descending)
            .sortChords(d3.descending);

        var arc = d3.svg.arc()
            .innerRadius(r0)
            .outerRadius(r0 + 40);  // Thickness of arc category

        var svg = d3.select("#chord") // Attach to the div element
            .append("svg:svg")
            .attr("width", w)
            .attr("height", h)
            .append("svg:g")
            .attr("id", "circle")
            .attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");

        svg.append("circle").attr("r", r0 + 50);

        var rdr = chordRdr(matrix, mmap);

        chord.matrix(matrix);

        var g = svg.selectAll("g.group")
            .data(chord.groups())
            .enter().append("svg:g")
            .attr("class", "group")


            g.append("svg:path")
                .style("stroke", "black")
                .style("fill", function(d) { return fill(d.index); })
                .attr("d", arc);

    var chordPaths = svg.selectAll("path.chord")
        .data(chord.chords())
      .enter().append("svg:path")
        .attr("class", "chord")
        .style("stroke", function(d) { return d3.rgb(fill(d.target.index)).darker(); })
        .style("fill", function(d) { return fill(d.target.index); })
        .attr("d", d3.svg.chord().radius(r0))
};

// blog-post - http://www.delimited.io/blog/2013/12/8/chord-diagrams-in-d3
//*******************************************************************
//  CHORD MAPPER 
//*******************************************************************
function chordMpr (data) {
  var mpr = {}, mmap = {}, n = 0,
      matrix = [], filter, accessor;

  mpr.setFilter = function (fun) {
    filter = fun;
    return this;
  },
  mpr.setAccessor = function (fun) {
    accessor = fun;
    return this;
  },
  mpr.getMatrix = function () {
    matrix = [];
    _.each(mmap, function (a) {
      if (!matrix[a.id]) matrix[a.id] = [];
      _.each(mmap, function (b) {
       var recs = _.filter(data, function (row) {
          return filter(row, a, b);
        })
        matrix[a.id][b.id] = accessor(recs, a, b);
      });
    });
    return matrix;
  },
  mpr.getMap = function () {
    return mmap;
  },
  mpr.printMatrix = function () {
    _.each(matrix, function (elem) {
      console.log(elem);
    })
  },
  mpr.addToMap = function (value, info) {
    if (!mmap[value]) {
      mmap[value] = { name: value, id: n++, data: info }
    }
  },
  mpr.addValuesToMap = function (varName, info) {
    var values = _.uniq(_.pluck(data, varName));
    _.map(values, function (v) {
      if (!mmap[v]) {
        mmap[v] = { name: v, id: n++, data: info }
      }
    });
    return this;
  }
  return mpr;
}
//*******************************************************************
//  CHORD READER
//*******************************************************************
function chordRdr (matrix, mmap) {
  return function (d) {
    var i,j,s,t,g,m = {};
    if (d.source) {
      i = d.source.index; j = d.target.index;
      s = _.where(mmap, {id: i });
      t = _.where(mmap, {id: j });
      m.sname = s[0].name;
      m.sdata = d.source.value;
      m.svalue = +d.source.value;
      m.stotal = _.reduce(matrix[i], function (k, n) { return k + n }, 0);
      m.tname = t[0].name;
      m.tdata = d.target.value;
      m.tvalue = +d.target.value;
      m.ttotal = _.reduce(matrix[j], function (k, n) { return k + n }, 0);
    } else {
      g = _.where(mmap, {id: d.index });
      m.gname = g[0].name;
      m.gdata = g[0].data;
      m.gvalue = d.value;
    }
    m.mtotal = _.reduce(matrix, function (m1, n1) { 
      return m1 + _.reduce(n1, function (m2, n2) { return m2 + n2}, 0);
    }, 0);
    return m;
  }
}

1 个答案:

答案 0 :(得分:0)

源和目标ID是互斥的(即没有源是目标,没有目标是源),并且您只是添加源的值,因此当布局算法查找任何目标时,它返回null并且最终在布局中作为NaN进行级联。

通过添加目标来解决:

.addValuesToMap('source')
.addValuesToMap('target')

问题是和弦图是否最好显示二分图,但似乎确实将两组保持在一起(可能只是因为它们是单独添加的)