D3.js 断弦图

D3.js 断弦图,d3.js,chord-diagram,D3.js,Chord Diagram,我在D3和弦图上遇到了问题 它使用了Steve Halls优秀的和弦映射器函数 虽然我过去在这方面取得了成功,但我得到的错误表明我的数据有问题(?) 错误:属性d:应为数字,“…66669 0 1,1” 娜娜,娜娜,娜娜……” 有人能帮我理解我可能做错了什么吗 var data = [ { "count": 1, "source": "6540", "target": "1030" }, { "count": 1, "source": "6

我在D3和弦图上遇到了问题

它使用了Steve Halls优秀的和弦映射器函数

虽然我过去在这方面取得了成功,但我得到的错误表明我的数据有问题(?)

错误:属性d:应为数字,“…66669 0 1,1” 娜娜,娜娜,娜娜……”

有人能帮我理解我可能做错了什么吗

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

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

通过添加目标来解决此问题:

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

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

谢谢。这很有帮助。