Issue with summing and data manipulation in d3

151
February 11, 2020, at 10:10 PM

I have a data set that i'm trying to work with in js.D3 and i'm struggling.

The dataset has the following attributes:

  1. Job Offers (Int)
  2. City (String)
  3. Date (DateTime)
  4. Industry (String)
  5. College Graduate (Boolean value)

I want to sum all job offers received by city by month and for some reason i'm coming up short and receiving an error.

First I have done the following to ensure I have clean data (I.E. no missing records etc):

const cleanJobData = data.filter(d=> d.city !=="" && d.dateTime !=="" && d.jobOffer !== "" && d.jobOffer!== 0)

I then tried to use d3.rollup to sum job offers by city:

const jobOffersByMonth = d3.rollup(cleanJobData,
                                           fcm => d3.sum(fcm, d=> d.jobOffer),
                                           d => d.dateTime.getMonth(), city => city.city);

This now gives me a map of months with corresponding totals for job offers by city. I want to now sort this from greatest to least by number of offers per city. if I try and use d3.sort() I receive an error that d3.sort is not a function. What am I doing wrong here?

I also tried using a group function const jobOffersByMonth = d3.group(cleanJobData, d => d.dateTime.getMonth(), v => v.city, fcm => d3.sum(fcm, v => v.jobOffers)) but I receive the error: T is not iterable

Answer 1

Can you please check if the following code fulfill your requirement.

const data = [{ 
    jobOffer: 23, 
    city: 'mumbai', 
    dateTime: new Date(2014, 1, 1), 
    industry: 'aa', 
  }, 
  { 
    jobOffer: 23, 
    city: 'delhi', 
    dateTime: new Date(2012, 1, 1), 
    industry: 'aa', 
  }, 
  { 
    jobOffer: 23, 
    city: 'delhi', 
    dateTime: new Date(2011, 2, 2), 
    industry: 'aa', 
  }, 
  { 
    jobOffer: 23, 
    city: 'pak', 
    dateTime: new Date(2013, 1, 1), 
    industry: 'aa', 
  }, 
] 
 
const cleanJobData = data.filter(d => d.city !== "" && d.dateTime !== "" && d.jobOffer !== "" && d.jobOffer !== 0); 
 
var nested_data = d3.nest() 
  .key(function(d) { 
    return d.city; 
  }) 
  .rollup(function(leaves) { 
    return d3.sum(leaves, function(d) { 
      return d.jobOffer; 
    }) 
  }) 
  .entries(cleanJobData) 
  .sort((a, b) => b.value - a.value) 
 
 
console.log(nested_data)

Answer 2

I believe that d3.sort is trying to use the Array sort function on d3 which is not an Array and therefore, it's true: d3.sort is not a function.

You would have to use sort on jobOffersByMonth (after converting it to an Array from a Map, which is what is returned after doing a rollup) and create an appropriate function to pass to it, perhaps taking advantage of d3's ascending or descending, like this user's answer here: https://stackoverflow.com/a/25168203/1168004 or

// given jobOffersByMonth looks something like:
// Map {
//      "{MONTH_NAME}" => int
// }
// we must first convert it into an Array to sort it 
// using Array.from(jobOffersByMonth) or [...jobOffersByMonth]
[...jobOffersByMonth].sort(function(x, y){
   return d3.ascending(x[1], y[1]); // could alternatively be descending
});
Rent Charter Buses Company
READ ALSO
How to prevent opening a new tab during scraping with puppeteer, when clicking a button with ng-click directive?

How to prevent opening a new tab during scraping with puppeteer, when clicking a button with ng-click directive?

When scraping a website containing a button that navigates to a pdf file when clicked, I would normally remove target="_blank" attribute to prevent from opening in a new tabHowever, this time around, clicking the button triggers some function like this: ng-click="$ctrl

444
Change CSS theme variable values with JS or Jquery [duplicate]

Change CSS theme variable values with JS or Jquery [duplicate]

How can I change the value of the variables inside this block [user-theme="theme"] with JS? I have the same variables in other blocks that should not be affected because I flip between them by changing the attribute value

177
canvas.toDataURL blocked by Brave Shield cross site device-recognition

canvas.toDataURL blocked by Brave Shield cross site device-recognition

I am currently working on a webapp which will be used to upload files after a resizeWhen I am working on localhost:3000, the resize process works like a charm, but when I am working on 192

169