score:0

having just run into this and it being particularly non-trivial, there's an abstraction of d3-sankey (unfortunately not drop-in) that allows you to set arbitrary orders (as well as do lots of other non-standard things like groups and cycles):

var layout = d3.sankey()
               .extent([[100, 10], [840, 580]]);

var diagram = d3.sankeydiagram()
                .linkcolor(function(d) { return d.color; });

d3.json('uk_energy.json', function(energy) {
  layout.ordering([
      [
        [
          "supply^indigenous",
          "supply^imports"
        ],
        [],
        []
      ],
      [
        [
          "primary^natural gas",
          "primary^bioenergy & waste",
          "primary^coal",
          "primary^manufactured fuel",
          "primary^primary electricity",
          "primary^electricity",
          "primary^petroleum products",
          "primary^primary oils"
        ],
        [
          "stocks^*"
        ],
        []
      ],
      [
        [
          "transfers^*",
          "transform^power stns",
          "transform^other transform",
          "transform^refineries"
        ],
        [],
        [
          "sink^*"
        ]
      ],
      [
        [
          "secondary^natural gas",
          "secondary^bioenergy & waste",
          "secondary^coal",
          "secondary^electricity",
          "secondary^manufactured fuel",
          "secondary^heat sold",
          "secondary^petroleum products"
        ],
        [
          "own use^*"
        ],
        [
          "loss^*"
        ]
      ],
      [
        [
          "use1^other",
          "use1^industry",
          "use1^transport"
        ],
        [],
        []
      ],
      [
        [
          "use^domestic",
          "use^public administration",
          "use^commercial",
          "use^agriculture",
          "use^miscellaneous",
          "use^unclassified",
          "use^iron and steel",
          "use^non-ferrous metals",
          "use^mineral products",
          "use^chemicals",
          "use^mechanical engineering etc",
          "use^electrical engineering etc",
          "use^vehicles",
          "use^food, beverages etc",
          "use^textiles, leather etc",
          "use^paper, printing etc",
          "use^other industries",
          "use^construction",
          "use^air",
          "use^rail",
          "use^road",
          "use^national navigation"
        ],
        [],
        []
      ]
    ]
  );
  d3.select('#sankey')
      .datum(layout(energy))
      .call(diagram);
});

according to the docs:

if ordering is specified, sets the node ordering to the specified value and returns this layout. if ordering is not specified, return the current value, which defaults to null.

when ordering is null, the node ordering will be calculated automatically.

when ordering is specified, it is used directly and no rank assignment or ordering algorithm takes place. the ordering structure has three nested lists: ordering is a list of layers, each of which is a list of bands, each of which is a list of node ids.

afaict, the carets (^) in the example denote groupname^nodename.

this might not be particularly helpful if you're deep into a project already, but if starting one from scratch this would probably be my first port of call.

score:3

below steps can be used to create sankey with custom node order.

 let data = {nodes:[],links:[]}

function to order/sort all nodes

 const sankey = d3.sankey()
    .size(graphsize)
    .nodeid(d => d.id)
    .nodewidth(nodewidth)
    .nodepadding(0.5)
    .nodealign(nodealignment)
    .nodesort(null) //creates sankey nodes as ordered in the data 

 let graph = sankey(data)

sankey documentation

score:5

if you set the layout iterations value to zero you'll get the nodes in their alphabetical (by name) order: that worked well enough for me.

var sankey = d3.sankey()
    .nodewidth(36)
    .nodepadding(40)
    .size([width, height])
    .layout(0);  /* <<<<<<< setting the iterations to zero */

score:6

removing the following line from the resolvecollisions() function in the sankey.js file will stop the order of the nodes from changing:

function resolvecollisions() {
    ...
    // nodes.sort(ascendingdepth);  // commented this out to prevent node reordering
    ...
}

the nodes will then be ordered vertically by however they are originally populated. so if you sort the nodes first before pushing the data, they will appear in sorted order.


Related Query

More Query from same tag