What are some ways to streamline this D3 script?

My CSV data displays pass rates by organisation for different years:

org,org_cat,2004_passed,2004_total,2005_passed,2005_total,2006_passed,2006_total
GSK,industry,35,100,45,100,55,100

I am using D3 and aiming to create a dictionary of organisations structured as follows:

data = {
 'GSK': {
     'org_cat': 'industry',
     'data': [
        { 'year': 2004, 'passed': 35, 'total': 100 },
        { 'year': 2005, 'passed': 45, 'total': 100 },
        { 'year': 2006, 'passed': 55, 'total': 100 }
     ]
  ]
}

The process seems clear except for the messy code handling the year columns:

var data = {};
allData.forEach(function(d) {
  data[d.org] = {
    'category': d.org_cat,
    'data': []
  };
  for (var k in d) {
    var temp = {};
    for (var k in d) {
      if (patt.test(k)) {
        var res = k.split("_");
        if (res[0] in temp) {
          temp[res[0]][res[1]] = +d[k];
        } else {
          temp[res[0]] = {};
          temp[res[0]][res[1]] = +d[k];
        }
      }
    }
    var tempArr = [];
    for (var y in temp) {
      var tempDict = {};
      tempDict.year = y;
      tempDict.passed = temp[y].passed;
      tempDict.total = temp[y].total;
      tempArr.push(tempDict);
    }
    // TODO: sort by year in case the keys got shuffled
    data[d.org].data = tempArr;
  }
});

Is there a simpler way to clean up this complex code?

We can assume each row represents a unique organisation.

Answer №1

There's no need for D3 in this scenario, as your code doesn't utilize it either. Below is an approach I would take, which might not be the most straightforward method, but it could still benefit you:

Check out the Jsfiddle example here: https://jsfiddle.net/thatOneGuy/dnvheznk/1/

In my implementation, I converted the data to JSON for JSFiddle usage. However, since you are already familiar with looping through CSV, simply update line 14 as follows:

for (var i = 0; i < data.length; i++) { //loop through data array (this allows scalability for larger arrays) 

You can modify it like this:

allData.forEach(function(d, i) { //make sure to add 'i' for indexing

The fully commented code with converted JSON data is provided below:

var data = [{ //data set converted to JSON for easier use
  "org": "GSK",
  "org_cat": "industry",
  "2004_passed": 35,
  "2004_total": 100,
  "2005_passed": 45,
  "2005_total": 100,
  "2006_passed": 55,
  "2006_total": 100
}];

var newData = {}; //new data container

for (var i = 0; i < data.length; i++) { //loop through data array (this is so you can use this on a bigger sized array)
  var thisObj = {}; //create empty object
  thisObj.org_cat = data[i].org_cat; //set org_cat
  thisObj.data = []; //initialize data array to populate later

  for (var key in data[i]) { //iterate through data[i]
    if (key != 'org' && key != 'org_cat') { //ensure the key is neither 'org' nor 'org_cat'
      var thisData = {}; //initialize data object
      var thisYear = key.toString().substring(0, 4); //extract year using substring

      thisData.year = thisYear; //assign year
      thisData.passed = data[i][thisYear + '_passed']; //assign passed value for this year
      thisData.total = data[i][thisYear + '_total']; //assign total value for this year

      thisObj.data.push(thisData); //add current data object to the data array
    }
  }

  var uniqueDates = []; //store unique items from the data array
  for (var j = 0; j < thisObj.data.length; j++) { //iterate over the data array created earlier
    if (uniqueDates.indexOf(thisObj.data[j].year) < 0) { //if the current year is not included in the unique array
      uniqueDates.push(thisObj.data[j].year); //add it
    } else {
      thisObj.data.splice(j--, 1); //remove duplicate data
    }
  }

  newData[data[i].org] = thisObj; //associate the data of the current organization with the object created above
}

console.log('newData', newData) //output new 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

The error message InvalidCharacterError is displayed when the attempt to create a new element using the 'createElement' method on the 'Document' object fails. This is due to the tag name provided ('/static/media/tab1.fab25bc3.png') not being a valid name

Hey everyone! I'm new to using React and I decided to try cloning Netflix by following a tutorial on YouTube. However, I've encountered an issue with rendering an image in a functional component. The error message I'm receiving is as follow ...

Associating user input information with an AngularJS object

Currently, I am working on a project that involves inputting a user's ID, first name, and last name. Once the input is received, a user object is created and stored inside the logins array. My goal is to display each new user as the next item in an u ...

ScriptManager is not accessible in the current ASP.Net Core Razor Page context

I'm facing an issue where I have a view (such as Index.cshtml) and a page model (like Index.cshtml.cs). In the view, there's a JavaScript function that I want to call from the OnPost() method in the page model. I tried using ScriptManager for thi ...

Is it permissible to access an iframe directly by its name?

I recently came across some JavaScript code that directly accesses an iframe by its name, without using getElementById() or any other method. Surprisingly, this code seems to be functioning properly in browsers like Chrome, Firefox, IE10, and Safari for Wi ...

What is the best way to implement a multi-row form in Vue.js?

Form Structure: <card-wrapper v-for="(passenger, index) in form.passenger" :key="index" :icon="['fas', 'user']" :title="`Passenger ${index + 1}`" class="mb-5" > <validation-observer ...

Components from Bower are currently not available

Trying to automate the injection of bower components into my HTML using grunt-wiredep. It seems simple enough, but I'm having trouble setting the correct path to the bower directory when running localhost. Currently, I'm receiving this error: ht ...

Tips for dynamically adding and removing keys from a JSON object

I am working on a code for a car rental website using jQuery mobile. I need to dynamically add and remove keys from a JSON object with true or false values. The goal is to make a selected car unavailable by changing the "available" key to either true or ...

Sending an object from Rails to Javascript

My MapsController is def show @outlet=OUtlet.all render 'maps/map' end In the view page map.html.erb, I iterate through each outlet to display their latitude and longitude: <% @outlet.each do |product| %> <%= product.latitu ...

A particular character is displayed exclusively in a text box using either jQuery or JavaScript

Text Box <input id="txtbo" type="text" value="CAN'T TOUCH THIS!" size="50" /> Solution Using jQuery or Javascript: var readOnlyLength = $('#txtbo').val().length; $('#txtbo').on('keypress, keydown', function(even ...

Node.js can provide a reusable email framework that can be used across

When it comes to sending emails based on specific business functions in nodejs, I have been following a particular approach. However, I am exploring the possibility of improving this method by composing email content more efficiently. Instead of hardcoding ...

What is the correct method to choose an element in jQuery based on the function's id parameter

I'm having trouble deleting an item in my to-do list app. deleteToDoItem: function(id) { $(id).remove(); console.log(id); }, Here is the function that calls deleteToDoItem: function deleteItem(event) { var itemID, splitID, t ...

Explore one of the elements within a tuple

Can we simplify mapping a tuple element in TypeScript? I'm seeking an elegant way to abstract the following task const arr: [string, string][] = [['a', 'b'], ['c', 'd'], ['e', 'f']] const f ...

Navigating through multiple pages with React Native stack navigation

I'm currently in the process of developing a react native app and I'm facing some confusion with regards to page navigation. It appears that there is a glitch in the navigation flow, causing it to skip a page. <NavigationContainer> ...

Basic game of tic tac toe using JavaScript and jQuery

Teaching myself the ropes of JavaScript/jQuery, I decided to dive into building a simple tic tac toe game. Following this example as a guide, I embarked on creating my own version. While most parts seem to be working smoothly, there's one problem that ...

I am in the process of creating several checkboxes and am looking to incorporate some added functionality

Currently, I am working on a project that involves creating multiple checkboxes. My goal is to implement a specific functionality where only one checkbox can be checked in each group with the correct or incorrect value. Once all groups have been selected, ...

How can you integrate Dygraph into your React project alongside redux?

Lately, I've been facing some challenges while trying to integrate Dygraph into React (utilizing Redux). The Dygraph wrapper packages available on NPM don't seem to cooperate. Furthermore, the conventional method of using: <div id="graph"> ...

Perform an operation in JQuery after a different operation has been completed

Recently, I came across this JavaScript function that displays a loading image for a few seconds before revealing a hidden div: <script type="text/javascript> $(document).ready(function () { $('#load').html('<img style="display ...

Troubleshooting Key Press Issues with Bootstrap 5 Dropdown and Collapse Feature

Exploration In my quest to create a dynamic Bootstrap (5) Navigation bar/menu with animated sub-menus, I stumbled upon a solution that seems to fit the bill perfectly. By employing data-bs-toggle="collapse" instead of 'dropdown', I dis ...

Unable to show the input's value

Need help in taking user input to display calculated values //html <div class="empty"> <h5> Enter Empty Seats </h5> <ion-item> <ion-input placeholder="Enter Number of Empties.." type="number" name="emptySeats" [( ...

The filter is displaying incorrect categories

I am facing an issue with creating a work filter based on the last column which represents categories. When I select an option from the dropdown, I want to display only that specific category and hide the others. Currently, when I try clicking on an option ...