Сломанная диаграмма аккордов D3js

У меня проблемы с диаграммой аккордов D3.

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

Он использует отличные функции 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 ответ

Решение

Идентификаторы источника и цели являются взаимоисключающими (т. Е. Источники не являются целями, цели не являются источниками), и вы только добавляете значения для источников, поэтому, когда алгоритм компоновки ищет любую цель, он возвращает ноль, и в конечном итоге это происходит как: NaNs в макете.

Решите, добавив цели тоже:

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

Существует вопрос о том, является ли диаграмма аккордов лучшей для отображения двудольного графа, но, похоже, она объединяет две группы (вероятно, только потому, что они были добавлены отдельно).

Другие вопросы по тегам