D3 Chord Duplication Prevention

This demo (not my code) compares two different categories of items to each other, so - unlike a chord diagram where any item can be connected to any other item - coffee shops cannot be connected to a coffee shop and states cannot be connected to states.

Some wedges look like this if Donkin donuts appear first:

enter image description here

But other wedges look like this if Starbucks has a higher value in state:

enter image description here

An unnecessary overlap in my opinion. The order of the elements should not be dictated by their value, but instead by the order of the elements to the left - that is, always Dunkin 'first.

I see the view that is happening in

 var chord = d3.layout.chord()
             .padding(.02)
             .sortSubgroups(d3.descending)

      

but I'm not sure how I can specify a custom sorting for the state items. It makes sense to sort the subgroups by coffee shop (or in ascending order), but conditions should not be treated the same way.

How do we know if a chord is a state or not? It looks like the information can be pulled by passing the chord to the rdr

function instance chordRdr

that binds matrix

, which is what is sorted for meta information from the object mmap

.

How do I create a conditional subgroup?

+3


source to share


2 answers


Short answer: you cannot do this in d3.

This is how d3 does the sort:

// Sort subgroups…
if (sortSubgroups) {
  subgroupIndex.forEach(function(d, i) {
    d.sort(function(a, b) {
      return sortSubgroups(matrix[i][a], matrix[i][b]);
    });
  });
}

      



Source

It will sort for each subgroup.

The only way you can finish this job is to create a custom copy d3.chord.layout()

, which can be found at the link above if you want to play around with it.

+2


source


I would not recommend using this solution :

//all the values in matrix are integers
//we can track the numbers that are starbucks stores
//by adding a small decimal to them
matrix = matrix.map(function(row){
  return row.map(function(d, i){
    return d + (i == row.length - 1 ? 1e-7 : 0) })
})

//now we can do a lexicographic sort 
//first checking for the presence of a decimal and then size
var chord = d3.layout.chord()
    .sortSubgroups(function(a, b){
      if (a != Math.round(a)) return false
      if (b != Math.round(b)) return true
      return b < a ? -1 : b > a ? 1 : 0;
    })

      



Modifying d3.layout.chord

or starting with something simpler that doesn't require a redundant matrix of values ​​will probably work better in most situations.

+1


source







All Articles