Mathnewbie
Mathnewbie

Reputation: 131

Data manipulation in D3.js

I have the following data:

var data = [
  {Name:"A", Var:"15", Temp:"20",Lo:"T"},
  {Name:"B", Var:"45", Temp:"40",Lo:"F"},
  {Name:"B", Var:"63", Temp:"340",Lo:"T"},
  {Name:"A", Var:"415", Temp:"450",Lo:"F"},
  {Name:"B", Var:"405", Temp:"940",Lo:"F"},
  {Name:"B", Var:"415", Temp:"410",Lo:"T"},
  {Name:"A", Var:"24", Temp:"51",Lo:"T"},
  {Name:"C", Var:"43", Temp:"40",Lo:"T"},
  {Name:"A", Var:"41", Temp:"40",Lo:"F"}
]

I filter the data to get

dataFiltered = [
  {Name:"A", Var:"15", Temp:"20",Lo:"T"},
  {Name:"A", Var:"415", Temp:"450",Lo:"F"},
  {Name:"A", Var:"24", Temp:"51",Lo:"T"},
  {Name:"A", Var:"41", Temp:"40",Lo:"F"}
]

But I want to have a new array of objects like:

dataNew = [
  {Vt:"35", Tv:"5"},
  {Vt:"865", Tv:"35"},
  {Vt:"75", Tv:"27"},
  {Vt:"80", Tv:"-1"}
]

Finally I want to use dataNew to present the aggregated data for Vt (35+865+75+80) and Tv (5+35+27-1) on a pie chart.

Note Vt = Var + Temp and Tv = Temp - Var from dataFiltered.

I really do not know what to do after filtering the data and in particular how to get dataNew.

I leave the code for the filtering part here as well.

var filteredData = data.filter(function(d) {
    return d.Name == "A";
});

Upvotes: 2

Views: 166

Answers (2)

Shidersz
Shidersz

Reputation: 17190

You can get all the output you need in one iteration over the original data using Array.reduce() to generate an object with the new array of data and the accumulated values for Vt and Tv, example:

var data = [
  {Name:"A", Var:"15", Temp:"20", Lo:"T"},
  {Name:"B", Var:"45", Temp:"40", Lo:"F"},
  {Name:"B", Var:"63", Temp:"340", Lo:"T"},
  {Name:"A", Var:"415", Temp:"450", Lo:"F"},
  {Name:"B", Var:"405", Temp:"940", Lo:"F"},
  {Name:"B", Var:"415", Temp:"410", Lo:"T"},
  {Name:"A", Var:"24", Temp:"51", Lo:"T"},
  {Name:"C", Var:"43", Temp:"40", Lo:"T"},
  {Name:"A", Var:"41", Temp:"40", Lo:"F"}
];

function reduceData(data, type)
{
    return data.reduce((acc, {Name, Var, Temp}) =>
    {
        if (Name !== type)
            return acc;

        let Vt = (+Var) + (+Temp), Tv = Temp - Var;
        let len = acc.newData.push({Vt, Tv});
        acc.acc_vt += Vt;
        acc.acc_tv += Tv;
        acc.avg_tv = (acc.avg_tv * (len-1) + Tv) / len;
        acc.avg_vt = (acc.avg_vt * (len-1) + Vt) / len;
        return acc;

    }, {newData: [], acc_vt: 0, acc_tv: 0, avg_vt: 0, avg_tv: 0})
}

console.log(reduceData(data, "A"));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Upvotes: 1

Code Maniac
Code Maniac

Reputation: 37775

You can map that filtered data to desired format using map and than you can use reduce to get total of Tv and Vt values

let dataFiltered = [{Name:"A", Var:"15", Temp:"20",Lo:"T"},{Name:"A", Var:"415", Temp:"450",Lo:"F"},{Name:"A", Var:"24", Temp:"51",Lo:"T"},{Name:"A", Var:"41", Temp:"40",Lo:"F"},]
        
let newData = dataFiltered.map(({Var, Temp}) => {
  let Vt = Number(Var) + Number(Temp)
  let Tv = Temp - Var
  return {Vt,Tv}  
})

console.log(newData)

let aggregateData = newData.reduce((op,{Tv,Vt})=>{
  op['Tv'] = op['Tv'] || 0
  op['Vt'] = op['Vt'] || 0
  op['Tv'] +=Tv
  op['Vt'] +=Vt
  return op
},{})

console.log(aggregateData)

Upvotes: 1

Related Questions