Klaus Hilgenfelder
Klaus Hilgenfelder

Reputation: 69

Nest data containing arrays with d3.nest

I am using d3 to make some pretty graphs, all of the same raw data. This raw data, however, contains arrays.

var data = [
{name: "Alfred", age: "27", medication: [{name: "Aspirin", dose: "14", unit: "tablets"}]}, 
{name: "Brian", age: "62", medication: []}, 
{name: "Chris", age: "46", medication: [{name: "Bisoprolol", dose: "3", unit: "ml"}, {name: "Clotrimazol", dose: "2", unit: "mg"}]}, 
{name: "David", age: "68", medication: [{name: "Aspirin", dose: "4", unit: "tablets"}, {name: "Bisoprolol", dose: "1.5", unit: "ml"}, {name: "Clotrimazol", dose: "2", unit: "mg"}]}
]

Now obviously, I can easily group those by, for example, age or name.

The problem arises when I want to show medications (by name), as any patient can have one, none, or several of those. Each patient can therefore be in none or several groups. So far, I see three ways of doing this:

  1. duplicate patients with more than one medication, each copy with a different single medication

This creates redundancies, also I want draw a whole barrage of diagrams from the same data. The key for nesting (the function that returns the value to group by for each patient) will be created dynamically from a user interface - as it is a getter, not a setter, I would need to figure out how to reset medication for each copy, too. The copying might, depending on the complexity of my raw data, also not be trivial.

  1. Concatenate medication names in the key function (with a unique separator) and split and add as needed when drawing.

Every occurring combination of medications will have its own group, and I would need to calculate sums from all groups containing a specific medication to get the total of it's frequency. This seems like a bad idea.

  1. Write my own nest function that handles arrays.

I would lose d3's rollup and sort functionality unless I implement that, too, from scratch.

Is there a better way?

Upvotes: 0

Views: 187

Answers (1)

Nixie
Nixie

Reputation: 637

I do not see a better way, except pre-processing your data (like your pt.1), so that the keys could be medication names, and values could be records from original data. You do not need to duplicate patients, you can just duplicate references to them, and that does not create a lot of redundancies (and saves memory). Instead of passing data into your charting function, you just pass extractMedications(data) instead, which is also not that really redundant.

function extractMedications(d)
{
    var res = [];
    d.forEach(function(patient) {
      patient.medication.forEach(function(medication) {
        res.push({medication_name: medication.name, patient: patient});
    })
  })
  return res;
}
console.log(extractMedications(data))

The other advantage that in this solution you can modify patient name in data array and that will be also reflected in the transformed array (because it holds a reference to the object from data)

Then you need to forward this structure to the d3.nest and do whatever you want.

Upvotes: 1

Related Questions