How to manipulate the reduce function in crossfilter in a way to create a certain array/object structure?

StackOverflow https://stackoverflow.com/questions/22741230

  •  24-06-2023
  •  | 
  •  

Question

I'm using crossfilter and am looking for a certain output after the reduce function:

var ndx = crossfilter(data);     
var alDim = ndx.dimension(function(d) { return d.al_code_unique; });
var seatsPaxAirline = alDim.group().reduce(
            function(a, d) {
                a.seats += d.seats;
                a.pax += d.pax;
                return a;
            },
            function(a, d) {
                a.seats -= d.seats;
                a.pax -= d.pax;
                return a;
            },
            function() {
                return  {seats:0, pax:0 }; }
            ).top(100);

seatsPaxAirline is now an array of objects like this:

[
{key: "5Y", value: {pax: 60, seats: 100}},
{key: "4Y", value: {pax: 50, seats: 90}},
{key: "3Y", value: {pax: 40, seats: 80}}
]

But I do need the following output from the crossfilter reduce function:

[
 {key: "5Y", value: [ {name: "pax", value: 60}, {name: "seats", value: 100}},
 {key: "4Y", value: [ {name: "pax", value: 50}, {name: "seats", value: 90}},
 {key: "3Y", value: [ {name: "pax", value: 40}, {name: "seats", value: 80}},
]

I feel it's just a question of changing the reduce function in a certain manner but unfortunately I have no clue. Could someone help me on this? Thanks in advance!

Was it helpful?

Solution

As far as I understand the question, you need to change your reduce function like so:

var seatsPaxAirline = alDim.group().reduce(
            function(a, d) {
                a[0].value += d.seats;
                a[1].value += d.pax;
                return a;
            },
            function(a, d) {
                a[0].value -= d.seats;
                a[1].value -= d.pax;
                return a;
            },
            function() {
                return  [{name: 'seats', value: 0}, {name: 'pax', value: 0}]; }
            ).top(100);

The key is in how you set up the reduceInitial function, as that will determine the data structure of your 'a' object that gets passed through the reduce.

OTHER TIPS

From what I understand, your input format is similar to:

var seatsPaxAirline = 
    [{key: "5Y", value: {pax: 60, seats: 100}},
     {key: "5Y", value: {pax: 40, seats: 100}},
     {key: "3Y", value: {pax: 30, seats: 100}},
     {key: "2Y", value: {pax: 70, seats: 100}},
     {key: "4Y", value: {pax: 50, seats: 100}},
     {key: "1Y", value: {pax: 45, seats: 100}},
     {key: "2Y", value: {pax: 50, seats: 100}},
     {key: "5Y", value: {pax: 60, seats: 100}},
     {key: "5Y", value: {pax: 65, seats: 100}},
     {key: "5Y", value: {pax: 55, seats: 100}}
     ];

And, you wish to group elements based on their key values like:

{
    "5Y": [{"key": "5Y", "value": {"pax": 60, "seats": 100}},
           {"key": "5Y", "value": {"pax": 40, "seats": 100}}, 
           {"key": "5Y", "value": {"pax": 60, "seats": 100}}, 
           {"key": "5Y", "value": {"pax": 65, "seats": 100}}, 
           {"key": "5Y", "value": {"pax": 55, "seats": 100}}],
    "3Y": [{"key": "3Y", "value": {"pax": 30, "seats": 100}}],
    "2Y": [{"key": "2Y", "value": {"pax": 70, "seats": 100}},
           {"key": "2Y", "value": {"pax": 50, "seats": 100}}],
    "4Y": [{"key": "4Y", "value": {"pax": 50, "seats": 100}}],
    "1Y": [{"key": "1Y", "value": {"pax": 45, "seats": 100}}]
}

If this is what you are looking to achieve using D3 then this is the way to do it:

d3.nest().key(function(d){return d.key}).map(seatsPaxAirline);

And, here's the working demo.


EDIT: I believe the sample object you've provided is malformed. But, if you modify the code I provided as shown below:

var output = d3.nest().key(function(d){return d.key}).map(seatsPaxAirline);
d3.entries(d3.entries(output).forEach(function(d,i){
  d.value.forEach(function(o,j){ 
    delete o["key"];
    d.value[j] = d3.entries(o.value);
  });
}));
output = d3.entries(output);

The output you'll get is:

[{
  "key": "5Y",
  "value": [
    [{"key": "pax","value": 60}, {"key": "seats","value": 100}],
    [{"key": "pax","value": 40}, {"key": "seats","value": 100}],
    [{"key": "pax","value": 60}, {"key": "seats","value": 100}],
    [{"key": "pax","value": 65}, {"key": "seats","value": 100}],
    [{"key": "pax","value": 55}, {"key": "seats","value": 100}]
  ]
}, {
  "key": "3Y",
  "value": [
    [{"key": "pax","value": 30}, {"key": "seats","value": 100}]
  ]
}, {
  "key": "2Y",
  "value": [
    [{"key": "pax","value": 70}, {"key": "seats","value": 100}],
    [{"key": "pax","value": 50}, {"key": "seats","value": 100}]
  ]
}, {
  "key": "4Y",
  "value": [
    [{"key": "pax","value": 50}, {"key": "seats","value": 100}]
  ]
}, {
  "key": "1Y",
  "value": [
    [{"key": "pax","value": 45}, {"key": "seats","value": 100}]
  ]
}]

This is as close as I can get it to the desired data structure. See if this is usable for you.

Updated Demo

PS: I realize that this isn't the most efficient of solutions but this is as good as it gets with me & D3. If you wish to fool around with the data structure, consider using underscoreJS.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top