Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using two datasets in one d3.js force-directed graph

I am still learning to use d3.js and I have hit a stumbling block which I hope someone can help with.

I have one data set of authors and one of published items with a many-to-many relationship: an author can publish many items and an item can have many authors. I would like to make a force-directed graph of authors and items together, therefore the links will always be between the two different datasets, never internally. I have all the nodes on the svg, but when I set up the d3.js I can only hand it one dataset for nodes:

d3.forceSimulation()
    .nodes(booksData)

So I cannot then give it a set of links which works across sets. Does anyone have any hints or help which might get me going again?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I have considered using categories and merging the datasets and colouring them by "category" but this would be a very inelegant solution which would require mashing up all the data from my API.

>Solution :

To link nodes from different datasets in a force-directed graph, you can create a third dataset that maps the relationships between the nodes. This third dataset would contain objects with two properties, source and target, that correspond to the indices of the nodes in the two original datasets.

Here’s an example of how you could create the third dataset from your existing data:

// Suppose booksData and authorsData are arrays of objects representing books and authors
// The arrays are assumed to be already populated from your API

// Create an empty array to hold the links
var links = [];

// Loop over each book
booksData.forEach(function(book) {
  // Loop over each author of the book
  book.authors.forEach(function(author) {
    // Find the index of the author in the authorsData array
    var authorIndex = authorsData.findIndex(function(a) {
      return a.id === author.id;
    });
    // Create a link object and push it onto the links array
    links.push({ source: book, target: authorsData[authorIndex] });
  });
});

// Now you can use the links array to create a force-directed graph
d3.forceSimulation()
  .nodes(booksData.concat(authorsData))
  .force("link", d3.forceLink().links(links))
  .on("tick", ticked);

In this example, book.authors is assumed to be an array of objects representing the authors of the book, and each author object has an id property that corresponds to the id of an author in the authorsData array.

Note that in this example, we’ve concatenated the booksData and authorsData arrays so that they can be passed as a single dataset to d3.forceSimulation(). You may want to keep the datasets separate if you need to apply different visual styles or behaviors to books and authors.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading