Search code examples
javascriptobjectd3.jsmean

How to calculate mean a property having condition on two other properties?


This is my data:

data = 
   [{ndc_description: "VIAGRA 50 MG TABLET", new_percent_change: 12.9, year: "2017"}, 
    {ndc_description: "VIAGRA 50 MG TABLET", new_percent_change: 12.9, year: "2019"}, 
    {ndc_description: "VIAGRA 50 MG TABLET", new_percent_change: 12.9, year: "2017"}, 
    {ndc_description: "JANUVIA 100 MG TABLET", new_percent_change: 4.41, year: "2017"},
    {ndc_description: "JANUVIA 100 MG TABLET", new_percent_change: 4.41, year: "2019"},
    {ndc_description: "JANUVIA 100 MG TABLET",new_percent_change: 4.41, year: "2017"}]

How can I mean the new_percent_change for each of two ndc_description and it's relative year? I want to add another column after "year" to contain calculated value.

Update: I could calculate the mean

roll = d3.rollups(data, v => d3.mean(v, d => d.new_percent_change), d => d.year, d => d.ndc_description)

but I don't know how to assign each value to the data array.


Solution

  • Since roll is an array of arrays with the means, you can do nested forEach loops to find the correct data object, tio which you will pass the mean:

    roll.forEach(yearArray => {
      yearArray[1].forEach(description => {
        const foundObj = data.filter(e => e.year === yearArray[0] && e.ndc_description === description[0]);
        foundObj.forEach(obj => obj.mean = description[1])
      })
    });
    

    Here's a demo, I changed some values so you can see the correct means:

    const data = [{
        ndc_description: "VIAGRA 50 MG TABLET",
        new_percent_change: 10.9,
        year: "2017"
      },
      {
        ndc_description: "VIAGRA 50 MG TABLET",
        new_percent_change: 12.3,
        year: "2019"
      },
      {
        ndc_description: "VIAGRA 50 MG TABLET",
        new_percent_change: 12.9,
        year: "2017"
      },
      {
        ndc_description: "JANUVIA 100 MG TABLET",
        new_percent_change: 8.41,
        year: "2017"
      },
      {
        ndc_description: "JANUVIA 100 MG TABLET",
        new_percent_change: 5.41,
        year: "2019"
      },
      {
        ndc_description: "JANUVIA 100 MG TABLET",
        new_percent_change: 4.41,
        year: "2017"
      }
    ];
    
    
    const roll = d3.rollups(data, v => d3.mean(v, d => d.new_percent_change), d => d.year, d => d.ndc_description);
    
    roll.forEach(yearArray => {
      yearArray[1].forEach(description => {
        const foundObj = data.filter(e => e.year === yearArray[0] && e.ndc_description === description[0]);
        foundObj.forEach(obj => obj.mean = description[1])
      })
    });
    
    console.log(data)
    <script src="https://d3js.org/d3.v7.min.js"></script>