The d3 hierarchy possesses the capability to compute the average values of child nodes

Looking for a solution with d3 visualization that involves averaging up the value of score on the lowest nodes and dynamically adding that average to the parent node above. It seems like there isn't an easy method in d3 for this task. The desired outcome is to transform the JSON object into the format shown in the second example below.

 {
  "name": "A1",
  "children": [
    {
      "name": "B1",
      "children": [
        {
          "name": "B1-C1",
          "children": [
            {
              "name": "B1-C1-D1",
              "children": [
                {
                  "name": "B1-C1-D1-E1",
                  "value": 30,
                  "score": 0.8
                },
                {
                  "name": "B1-C1-D1-E2",
                  "value": 35,
                  "score": 0.5
                }
              ]
            },
            {
              "name": "B1-C1-D2",
              "children": [
                {
                  "name": "B1-C1-D2-E1",
                  "value": 31,
                  "score": 0.4
                },
                {
                  "name": "B1-C1-D2-E2",
                  "value": 23,
                  "score": 0.7
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

The ideal final JSON output:

{
  "name": "A1",
  "scoreAvg": 0.625,
  "children": [
    {
      "name": "B1",
      "scoreAvg": 0.625,
      "children": [
        {
          "name": "B1-C1",
          "scoreAvg": 0.625,
          "children": [
            {
              "name": "B1-C1-D1",
              "scoreAvg": 0.7,
              "children": [
                {
                  "name": "B1-C1-D1-E1",
                  "value": 30,
                  "score": 0.8
                },
                {
                  "name": "B1-C1-D1-E2",
                  "value": 35,
                  "score": 0.6
                }
              ]
            },
            {
              "name": "B1-C1-D2",
              "scoreAvg": 0.55,
              "children": [
                {
                  "name": "B1-C1-D2-E1",
                  "value": 31,
                  "score": 0.4
                },
                {
                  "name": "B1-C1-D2-E2",
                  "value": 23,
                  "score": 0.7
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Answer №1

If you want to calculate the average score in a nested object, you can achieve this using a recursive function:

const obj = {
  "name": "A1",
  "children": [{
    "name": "B1",
    "children": [{
      "name": "B1-C1",
      "children": [{
          "name": "B1-C1-D1",
          "children": [{
              "name": "B1-C1-D1-E1",
              "value": 30,
              "score": 0.8
            },
            {
              "name": "B1-C1-D1-E2",
              "value": 35,
              "score": 0.5
            }
          ]
        },
        {
          "name": "B1-C1-D2",
          "children": [{
              "name": "B1-C1-D2-E1",
              "value": 31,
              "score": 0.4
            },
            {
              "name": "B1-C1-D2-E2",
              "value": 23,
              "score": 0.7
            }
          ]
        }
      ]
    }]
  }]
}

function getWithAverageScore(objToRecurse) {
  // If the current node has a score, return it
if (objToRecurse.score) {
return objToRecurse;
}
  // Otherwise, calculate and set the average score of its children recursively
const children = objToRecurse.children.map(getWithAverageScore);

return {
...objToRecurse,
children,
    // Calculate the average score based on children's scores or average scores
scoreAvg: children.reduce((total, { score, scoreAvg }) => total + (score || scoreAvg), 0) / children.length
};
}

console.log(JSON.stringify(getWithAverageScore(obj), null, 2))

Answer №2

let data = {
  "name": "Parent",
  "children": [
    {
      "name": "Child1",
      "children": [
        {
          "name": "Grandchild1",
          "children": [
            {
              "name": "GreatGrandchild1",
              "children": [
                {
                  "name": "GGC1-Child1",
                  "value": 30,
                  "score": 0.8
                },
                {
                  "name": "GGC1-Child2",
                  "value": 35,
                  "score": 0.5
                }
              ]
            },
            {
              "name": "GreatGrandchild2",
              "children": [
                {
                  "name": "GGC2-Child1",
                  "value": 31,
                  "score": 0.4
                },
                {
                  "name": "GGC2-Child2",
                  "value": 23,
                  "score": 0.7
                }
              ]
            }
          ]
        }
      ]
    }
  ]
};


function calculateAverageScore(obj){
  obj.avgScore = 0;
if(obj.children){
  for(child of obj.children){
    obj.avgScore += calculateAverageScore(child);
   }
obj.avgScore =  obj.avgScore /Math.max(1,obj.children.length);
   return obj.avgScore;
}else{
return obj.score;
}
}

calculateAverageScore(data);

console.log(JSON.stringify(data));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on making API calls in AngularJS using query strings

I am new to learning about AngularJS and recently came across a helpful article on connecting to an API and using its data in our app. The article specifically focuses on displaying weather information with AngularJS. The only downside is that the weather ...

javascript/jquery: ensure Android device displays content in full-screen mode

Currently working on developing a web app specifically for an android device that needs to be displayed in fullscreen mode. I came across the code snippet above on stack overflow, which successfully activates fullscreen mode upon click event. However, I a ...

Recursive instruction malfunctioning

I'm currently trying to develop a custom recursion directive, but unfortunately it's not functioning as expected. I have followed the instructions outlined here: Recursion in Angular directives For reference, you can view the fiddle here: http ...

toggle visibility of a div using AngularJS

Struggling to hide/show a div using AngularJS, I have gone through multiple tutorials with no success. Finally opted for the code snippet mentioned in this link, but still facing issues. Can anyone assist me in identifying the problem? PS: Using angular ...

What is the best method for transmitting a PHP object via Ajax using JSON format?

Here is the ajax code snippet I am currently using: $.ajax({ type: 'post', url: '/conversation/test', data: { conversation: JSON.stringify(<?php echo json_encode($conversat ...

Using Vue components in NativeScript-Vue popups: A comprehensive guide

To initiate the popup, I include the following code in a root component: import parentt from "./parentt.vue"; . . . this.$showModal(parentt, { fullscreen: true, }); The contents of parentt.vue are as follows: <template> <StackLayout> ...

Guide on implementing a bootstrap loading spinner during the process of retrieving data from an external api

Is there a way to use the bootstrap load spinner to mask the delayed information retrieval from a url and enhance the website's interactivity? ...

Encountering a glitch while iterating through function results in failure after the initial modification

I am facing some errors with the script provided below: var sections = ["#general_info", "#address_records", "#employment_history", "#driver_experience", "#military_experience", "#eeo_survey", &qu ...

Guide on integrating a plain Service/Provider into nest.js

I recently created a basic TypeScript class in nest.js called JwtTokenService.js. // JwtTokenService.js import { Injectable, Optional } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { JwtPayload } from ' ...

Can you explain the functionality of the DataTable drawCallback feature?

I'm currently facing an issue where CSS is not being applied to all cells in a DataTable based on their values when using drawCallback(). While the CSS gets applied to some cells, it's inconsistent. You can check out the JsFiddle of my problem he ...

Incorporating a Custom CKEditor5 Build into an Angular Application

I am currently in the process of developing an article editor, utilizing the Angular Integration for CKEditor5. By following the provided documentation, I have successfully implemented the ClassicEditor build with the ckeditor component. Below are the ess ...

Use a swipe gesture to move through the slideshow on a touchscreen device

I am currently working on a slideshow that allows users to navigate through images by clicking either the next or previous buttons. When a user clicks on one of these buttons, the next or previous image is loaded into the img src, as shown below. In addit ...

Present the array elements in a format that allows the user to easily choose an option and explore the content

I'm currently working on a project where users will take a Computer Based Test and be graded on a selected subject. I have a database set up with questions and multiple choice options. My goal is to display the questions in a way that allows users to ...

jQuery AJAX Triggered Only Once in Callback Function

I am facing an issue with the jQuery get function within my updateMyApps. The function works fine when called directly after it is declared. It successfully loops through the data and appends elements to the DOM. However, when I submit the form #addapplic ...

Setting up computed properties in VueJSSetting up computed values in

I am currently working on developing a lottery number service, and I am curious about how to set up computed properties. I came across the Vue.js documentation for computed properties at https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties. I tr ...

Struggling to align nested grids in the center

I'm currently following a mobile-first approach in designing my website. The entire website is contained within one main grid, and I also want to include smaller grids that will serve as links to other HTML pages. I created a sample nested grid but am ...

Issues with audio and video playback intermittently occurring on Sencha Touch 2

As a beginner with Sencha Touch 2, I am currently working on uploading images onto an iPad using Xcode. My app has audio playing on the home screen, and I want the video to start playing and the audio to stop when a specific tab is selected. However, the ...

Refresh the Document Object Model (DOM) and transmit the present time

I am having an issue with sending the actual current time when a button is clicked. Instead of getting the current time, I am receiving the time when the page initially loaded. This button is used to submit a form on Google Sheets using an API. This is th ...

The Ajax POST functionality appears to be malfunctioning, whereas the PHP equivalent is operating without any

Need assistance in developing a JavaScript mobile app that will POST an authentication token to a Microsoft website. Attempting to use online JavaScript code found, but encountering failures. The JavaScript code outputs a message "GET undefined/proxy/htt ...

Tips for serializing canonical/normalized JSON data using PHP

In PHP, the order of keys in JSON is not significant. The json_encode function will use the internal order of keys when converting to JSON format. It is important for me to ensure that identical JSON data is always serialized in the same way. Take for exam ...