5

I am trying to create a custom reduce function for a dataset attribute group that would sum a number of unique values for another attribute.

For example, my dataset looks like a list of actions on projects by team members:

{ project:"Website Hosting", teamMember:"Sam", action:"email" }, { project:"Website Hosting", teamMember:"Sam", action:"phoneCall" }, { project:"Budjet", teamMember:"Joe", action:"email" }, { project:"Website Design", teamMember:"Joe", action:"design" }, { project:"Budget", teamMember:"Sam", action:"email" } 

So, team members work on a variable number of projects by performing one action per line. I have a dimension by team member, and would like to reduce it by the number of projects (uniques).

I tried the below (storing project in a uniques array) without success (sorry, this might hurt your eyes):

var teamMemberDimension = dataset.dimension(function(d) { return d.teamMember; }); var teamMemberDimensionGroup = teamMemberDimension.group().reduce( // add function(p,v) { if( p.projects.indexOf(v.project) == -1 ) { p.projects.push(v.project); p.projectsCount += 1; } return p; }, // remove function(p,v) { if( p.projects.indexOf(v.projects) != -1 ) { p.projects.splice(p.projects.indexOf(v.projects), 1); p.projectsCount -= 1; } return p; }, // init function(p,v) { return { projects:[], projectsCount:0 } } ); 

Thanks a lot!

Edit after DJ Martin's answer ::

So, to be clearer, I would like to get the numbers I am after here would be:

----------- Sam : 2 (projects he is workin on, no matter the number of actions) Joe : 2 (projects he is workin on, no matter the number of actions) ----------- 

The answer provided by DJ Martin gets me there. But rather than hard coding a table, I would like to find a way to use these numbers for my DC.JS bar chart. When I was only using the number of actions (so just a reduceCount() ), I did it like below:

teamMemberChart.width(270) .height(220) .margins({top: 5, left: 10, right: 10, bottom: 20}) .dimension(teamMemberDimension) .group(teamMemberDimensionGroup) .colors(d3.scale.category20()) .elasticX(true) .xAxis().ticks(4); 

I guess there might be something to change in the group().

1 Answer 1

16

UPDATED ANSWER

Sorry I misunderstood the question... you are actually on the right track. You'll just need to maintain a count of each project so that your subtract function can know when to remove the value.

teamMemberGroup = teamMemberDimension.group().reduce( function (p, d) { if( d.project in p.projects) p.projects[d.project]++; else p.projects[d.project] = 1; return p; }, function (p, d) { p.projects[d.project]--; if(p.projects[d.project] === 0) delete p.projects[d.project]; return p; }, function () { return {projects: {}}; }); 

Here is an updated fiddle: http://jsfiddle.net/djmartin_umich/3LyhL/

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks a lot for your answer! It did not cross my mind to combine fields but it makes a lot of sense. The issue I have with this solution is that the end result doesn't really produce the numbers I am after. Sorry if it was not clear, but I try to obtain something like: Sam - (workin on) 2 projects (no matter how many actions) Joe - (workin on) 2 projects (no matter how many actions)
Ahh, I see. Updated the answer to achieve this.
Also I think the associative array {} helped in this case.
Great, thanks! That gives me the numbers (although I am still unsure why my solution did not work - maybe I should not use an array in this function). I have added the last bit of my problem because I cannot see how to feed these numbers to the chart.
@Koba - The d3 repository moved, references are now updated. Thanks.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.