1

My JSON looks like this (with some extra records that I'm not including for brevity)

[{"name":"Jim","category":"TechSupport","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":2,"Management":0,"Sales":0},
{"name":"Jim","category":"Management","month":"8",year:"2012","Date":"2012-08-01T04:00:00.000Z", "TechSupport":0,"Management":3,"Sales":0}]

My stack looks like this

var stack = d3.stack().keys(["TechSupport", "Management", "Sales"])
var series = stack(data)

The results of my stack look like [[0,2],[0,0]],[[2,2],[3,3]],[[1,1],[3,3]]

My code for displaying the barchart over the timescale looks like this

var groups = mainChart.selectAll("g")
.data(series)
.append("g")

groups.selectAll("rect")
.attr("id","bar")
.attr("fill", function(d){return colors(d.data.category)})
.attr("x", function(d){return xScale(d.data.Date);}}
.attr("y", function(d){return yScale(d[1]);})
.attr("width", 20)
.attr("height" return yScale(d[0]) - yScale(d[1])})

I can get everything to display along the timeline correctly except when I have items that have the same date, those are not stacking and I'm not sure why?

3TW3
  • 337
  • 1
  • 3
  • 14
Jamie
  • 428
  • 6
  • 24
  • 1
    Can you make a fiddle and be more specific what you are trying to achieve? I think it will help me to understand the problem. – 3TW3 Sep 21 '17 at 19:19
  • Yes, here you got. If you notice it isnt stacking it's just overlaying on the same date, where it should stack. https://jsfiddle.net/jamiebrs/pzdbddah/ – Jamie Sep 22 '17 at 18:25
  • I believe something is wrong with your stacked data in "series". – 3TW3 Sep 26 '17 at 12:03
  • Not disagreeing with that, but what specifically? Essentially I'm trying to show the number of times a person has worked in a department in a month, and if they have worked more than one department in the same month show that data stacked, looking at the JSON what can I add or change to it to make this work? – Jamie Sep 27 '17 at 14:48
  • First you made a small error. In your forEach function `TechSupport` should be replaced with `Techsupport`. This will solve the fact that you have `Management` values in your series that shouldn´t be there. Secondly you have a JSON with 5 objects based upon the original dataset, that should be 4 based upon the unique date entries. The 2 objects with March 2013 should be combined to one. Then you have a good JSON for the stack function. I hope I´m giving you a good direction. – 3TW3 Sep 27 '17 at 19:47
  • I fixed my fiddle in my foreach to fix that issue. As far as the 4 json objects vs 5, how would I go about doing that? I am fairly new to D3, so this is a learn as I go thing. I tried doing a nest and using the d.Date for my key then using .entries(data) but my bars are now disappeared, check out my fiddle to see what I am talking about, and feel free to fork it if you need to do so to explain better. – Jamie Sep 28 '17 at 18:12

1 Answers1

1

Preparing dataset - forEach()

In your forEach function I've changed two small errors.

Changed Techsupport to TechSupport like I mentioned earlier:

else if(d.category == 'Techsupport')

and by the cattotal of Management I've added a + to it:

d.Management = +d.cattotal;

Preparing dataset - reduce()

You have a JSON with several objects based upon the original dataset. This dataset must be reduced based upon the unique date entries. The object values should be combined. Then you have a good JSON for the stack function.

This can be achieved in several ways. I use a reduce() function like the one below:

var dataset = [];
data.reduce(function(res,obj){
   var key = obj.Date;
   if (res[key]){
       res[key].Sales +=obj.Sales;
       res[key].Techsupport +=obj.Techsupport;
       res[key].Management +=obj.Management;
   } else {
       dataset.push(o);
       res[key] = obj;
   }
   return res;
}, {});

The dataset contains the well prepared data for the stack function. However, I didn't want to replace data with dataset in your entire code, so I easily updated data:

data = dataset;

You are free to choose otherwise of course.

Responsive y-axis:

The y-axis must be automatically adapted to the stacked bars so I changed your yMax like:

var yMax = d3.max(series[series.length - 1], function(d) { return d[1]; });

Updating drawing the stacked bars and tooltips

Finally I updated your stacked bars by adjusting the fill attribute. I changed it for both your main and nav chart.

.attr("fill", function(d){ return colors(d3.select(this.parentNode).datum().key)})

For the tooltips I've updated the Key and Total values:

div.html("Date: " +d.data.Date + "<br>" + "Category: " + d3.select(this.parentNode).datum().key + "<br>" + "Total:" + (d[1]-d[0]))

In this fiddle you can find a working example.

3TW3
  • 337
  • 1
  • 3
  • 14
  • So in implementing this I found a bug that I am unsure why it happens. I have updated my fiddle, take a look at the stack for Jan 2012. It has 3 data items (originally) and 3 categories, yet when displayed it doesnt appear stacked and it is displaying Sales twice? Secondly is there a way using this .reduce approach to determine the highest "stacked" value for my y Axis? here is the fiddle again https://jsfiddle.net/jamiebrs/pzdbddah/ – Jamie Sep 29 '17 at 20:37
  • How do you want to implement the differtent persons (James, Jim,...) into the graph? Should we take the sales of Jim and James on a date together (add up)? – 3TW3 Sep 30 '17 at 08:08
  • 1
    The different persons are not really relevant, the page actually only allows for one person I just put in hand jammed data because I couldnt directly copy it from my other network, if fact I already made James Jim so as not to confuse the issue. Essentially there can only be one person for this graph and that person could work in any of 3 departments in a month and i need to stack his monthly work totals and display it over time using the stack to show the counts per department broken up as colors like we are doing but a total for the month of all departments along the y axis – Jamie Sep 30 '17 at 15:12
  • Still stuck on this one. Not sure why the stack isn't working? – Jamie Oct 03 '17 at 18:21
  • I'm close. The problem is the dataset preparation. I hope to post the solution soon :) – 3TW3 Oct 03 '17 at 19:24
  • Yeah that is what I am running into as well. – Jamie Oct 03 '17 at 20:21
  • I posted a updated answer and a fiddle. I didn't change the tooltips, you have to follow the same procedure as the fill attribute. – 3TW3 Oct 04 '17 at 20:35
  • Outstanding I got it working sans the tooltip which I am trying to follow what you did with the fill to get that working. Essentially you moved the fill up to the group level so that you can get the key, however I'm not entirely sure how to do that for the category? When I move the mouse over function to the group and do a console.log on d for the mouseover all I get is the numbers for the stack? How can I get the category and other data in the node? – Jamie Oct 05 '17 at 17:02
  • The same procedure wasn't a good idea afterall. I've moved the fill attribute back to the nodes and linked to its parent. For the tooltips I did the same for the key. The tooltip value is also updated. I believe everything is working as it should be :) – 3TW3 Oct 06 '17 at 13:06
  • 1
    Ok that all makes sense now. Lesson in this, see if you can get the data grouped before you send it down to D3. :) – Jamie Oct 06 '17 at 14:49