Creating a bar chart by using d3.layout.stack() and parsing data from a CSV file

Mike Bostock's Stacked-to-Grouped example showcases a data generation method that I find intriguing. However, since I have my own data stored in a CSV file, my main focus is on deciphering his approach and adapting it to work with my data instead.

// Inspired by Lee Byron's test data generator.
function bumpLayer(n, o) {

  function bump(a) {
    var x = 1 / (.1 + Math.random()),
        y = 2 * Math.random() - .5,
        z = 10 / (.1 + Math.random());
    for (var i = 0; i < n; i++) {
      var w = (i / n - y) * z;
      a[i] += x * Math.exp(-w * w);
    }
  }

  var a = [], i;
  for (i = 0; i < n; ++i) a[i] = o + o * Math.random();
  for (i = 0; i < 5; ++i) bump(a);
  return a.map(function(d, i) { return {x: i, y: Math.max(0, d)}; });
}

Understanding this code, especially when manipulated as shown below, can be challenging:

n = 6, // number of layers
m = 12, // number of samples per layer
stack = d3.layout.stack(),
layers = stack(d3.range(n).map(function() { return bumpLayer(m, .1); })),

To see the steps in action, check out my working code example here:

GOAL: My objective is to transform my csv file into a 2D array that can be processed by d3.

Although the following snippet doesn't work for me, it serves as a starting point:

// store the names of each column in csv file in array
var headers = ["Under $1000","$1000-$9999","$10000-19999","$20000-99999","100K - $999999","Over $1 Million"];


var myData = function(mycsv){

    d3.layout.stack()(headers
              .map(function(value){
                      return mycsv.map(function(d) {

                        return {x: d.Category, y: +d[value]};
                      });
                 }))
};

Thank you!

*EDIT***

In another example using d3.layout.stack() and csv, the parsing code looks like this:

d3.csv("crimea.csv", function(crimea) {

  // Transpose the data into layers by cause.
  var causes = d3.layout.stack()(["wounds", "other", "disease"].map(function(cause) {
    return crimea.map(function(d) {
      return {x: parse(d.date), y: +d[cause]};
    });
  }));

  // Compute the x-domain (by date) and y-domain (by top).
  x.domain(causes[0].map(function(d) { return d.x; }));
  y.domain([0, d3.max(causes[causes.length - 1], function(d) { return d.y0 + d.y; })]);

Check out the example here: http://bl.ocks.org/mbostock/1134768

Answer №1

To unlock the secrets of the stacked var chart, one must delve into the inner workings of d3.layout.stack(). For a comprehensive understanding, refer to the d3 wiki page linked here: https://github.com/mbostock/d3/wiki/Stack-Layout

The following approach combines the utilization of d3.csv and the d3 stack layout:

d3.csv("kick.csv", function (data){

    // Each string represents a column in the csv file, although this hardcoded method is not ideal
    var headers = ["Under $1000","$1000-$9999","$10000-19999","$20000-99999","100K - $999999","Over $1 Million"];

    // Category denotes the starting strings for each row, while priceRange pertains to the data values 
    var layers = d3.layout.stack()(headers.map(function(priceRange) {
        return data.map(function(d) {
          return {x: d.Category, y: +d[priceRange]};
        });
    }));

    // Insert remaining d3js chart code
});

You can find the complete code on GitHub: https://github.com/DeBraid/www.cacheflow.ca/blob/chart/styles/js/d3kickchart.js

UPDATE: I have created a tutorial video explaining this solution in depth: http://youtu.be/n9kKdbzCiLI

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

How to use the var keyword in JavaScript to declare block-scoped variables

At this moment, my goal is to establish a block-scoped variable in JavaScript by utilizing the var keyword. I prefer not to utilize the let keyword due to compatibility issues with certain browsers in ecma6. Is there an optimal and universal method to ac ...

Clicking on a button will allow me to select only a portion of text within a specific cell of

Inside a table, there is a paragraph of text enclosed in a <td></td> element. Take for example the following passage. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard ...

Angular 4: activating a function from a template

In my Angular 4 project, I am trying to calculate the average of some numbers. Here is a simplified version of my component: @Component({ selector: 'app-home', templateUrl: './home.component.html' }) export class HomeComponent { ...

What is the best way to organize the password reset process for Firebase authentication?

Exploring the possibilities with the Firebase authentication solution for user registration and login in my Ionic application has led me to a hurdle in implementing the 'password reset flow'. When a user forgets their password, the current flow ...

Using jQuery or JavaScript to delay execution until the image width has been adjusted

I'm encountering a timing issue with the loading functions on my page. The problem arises when I need to retrieve the width of an image after two specific events have occurred: 1) The image has finished loading 2) The image's width has been adj ...

A guide to turning off tab discarding in Google Chrome with JavaScript

Is there a way to prevent Chrome from discarding tabs on chrome://discards/ using JavaScript so that the tab remains open even after closing the page or browser? I am aware that this can be achieved with an extension, but I am interested in creating my o ...

React state will only return a single element

I've been working on updating the state and using the updated state for rendering. After I click and make modifications (such as adding {isClicked: true} to an array), the console.log(this.state.listOfQuotes) within the onClicked function displays t ...

AngularJS: Enhancing User Experience by Preserving View State and Setup through Routes

Is it possible in a single page application to switch back and forth between AngularJS routes while maintaining the same state? Traditionally, this would involve binding data in a parent scope. However, for views with extensive graphical elements, this me ...

Next.js project encountered a TypeError with message [ERR_INVALID_ARG_TYPE]: The "to" argument is expected to be a string type

While working on a Next.js application, I came across a TypeError that is linked to the undefined "to" argument. This issue pops up when I launch my development server using npm run dev. Despite checking my environment setup and project dependencies, I hav ...

Slideshow Display Suddenly Halts at the Last Image

I am currently working on a Bootstrap JS Carousel that showcases several images stored in the project folder. Each image's filepath is retrieved from an SQL Server database and displayed within the carousel. While the images are displaying correctly ...

Implementing Google Places reviews on a website with the help of JavaScript

Struggling to display the Google reviews for my company on our website, I can't seem to make it work. I've attempted to use this code: <script> $(function() { var people = []; $.getJSON('https://maps.googleapis.com ...

Is there a way to send a request before opening a new page that doesn't involve using synchronous XMLHttpRequest on the main thread, which is

With the deprecation of synchronous XMLHttpRequest, I am curious about any potential alternatives to achieve a similar behavior. Non-blocking asynchronous XMLHttpRequests may not always be suitable for specific cases. I am specifically referring to a scen ...

What is the best way to fill HTML tables using an ajax response?

This is a Laravel blade view/page that requires updating without the need to refresh the entire page. The blade.php code functions correctly and retrieves data from a MySQL database, but there seems to be an issue with the AJAX and JavaScript implementati ...

Exploring the capabilities of Jasmine 2.0 by testing an AngularJS factory method that returns a promise

When attempting to test a function that returns a promise, I encounter the following error: "Error: Timeout - Async callback was not invoked within the timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. " The specification I am using is as follo ...

What is the best way to notify the price range slider value using jQuery?

I am trying to implement a price range slider on my website. However, when I slide the range slider, instead of getting the value in the alert box, it shows [objectobject]. I am not sure why this is happening. Can someone help me figure out how to display ...

Is it possible to simultaneously toggle buttons and submit a form?

I am currently working on a functionality that involves toggling the display of two buttons and submitting a form. Code toggleButtons() { var btn1 = document.getElementById("start"); var btn2 = document.getElementById("pause"); if (btn1.style. ...

Adding a detached element under certain conditions

When attempting to add a detached span based on a specific condition, I encountered the following situation. const arrow = d3 .create('span') .classed('arrow', true) .text('\u2192'); //d3.select('bod ...

What is the best method for comparing two elements effectively in JavaScript?

Check out this code snippet that ensures txtKeyword input is focused when a key is pressed by the user. var txtKeyword = document.getElementById("txtKeyword"); ... document.addEventListener("keypress", function(event) { if(event.src ...

What is the best way to transfer the window object from the current tab to the extension?

I am looking to retrieve user storage data (local and session) from a specific tab, similar to what is shown in this app (see screen below). From my understanding, I need to access the window object of the active tab. While I have obtained the object, I a ...

Enhance your ChartJS visualizations by updating your charts with multiple datasets

Seeking a way to update both datasets in my chart without having to destroy and recreate it. chart2 = window.TrafficChart; chart2.data.labels = data.timestamps; console.log(data.traffic_tx); chart2.data.datasets[0] = data.traffic_rx; chart2.data.d ...