Skip to content

Commit 1544e71

Browse files
committed
Optimize and refactor groupby
1 parent 695ad68 commit 1544e71

File tree

1 file changed

+44
-39
lines changed

1 file changed

+44
-39
lines changed

src/transforms/groupby.js

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -116,43 +116,23 @@ exports.supplyDefaults = function(transformIn) {
116116
* array of transformed traces
117117
*/
118118
exports.transform = function(data, state) {
119+
var newTraces, i, j;
119120
var newData = [];
120121

121-
for(var i = 0; i < data.length; i++) {
122-
newData = newData.concat(transformOne(data[i], state));
122+
for(i = 0; i < data.length; i++) {
123+
newTraces = transformOne(data[i], state);
124+
125+
for(j = 0; j < newTraces.length; j++) {
126+
newData.push(newTraces[j]);
127+
}
123128
}
124129

125130
return newData;
126131
};
127132

128-
function initializeArray(newTrace, a) {
129-
Lib.nestedProperty(newTrace, a).set([]);
130-
}
131-
132-
function pasteArray(newTrace, trace, j, a) {
133-
Lib.nestedProperty(newTrace, a).set(
134-
Lib.nestedProperty(newTrace, a).get().concat([
135-
Lib.nestedProperty(trace, a).get()[j]
136-
])
137-
);
138-
}
139-
140-
// In order for groups to apply correctly to other transform data (e.g.
141-
// a filter transform), we have to break the connection and clone the
142-
// transforms so that each group writes grouped values into a different
143-
// destination. This function does not break the array reference
144-
// connection between the split transforms it creates. That's handled in
145-
// initialize, which creates a new empty array for each arrayAttr.
146-
function cloneTransforms(newTrace) {
147-
var transforms = newTrace.transforms;
148-
newTrace.transforms = [];
149-
for(var j = 0; j < transforms.length; j++) {
150-
newTrace.transforms[j] = Lib.extendDeepNoArrays({}, transforms[j]);
151-
}
152-
}
153133

154134
function transformOne(trace, state) {
155-
var i, j;
135+
var i, j, k, attr, srcArray, groupName, newTrace, transforms;
156136
var opts = state.transform;
157137
var groups = trace.transforms[state.transformIndex].groups;
158138

@@ -172,22 +152,31 @@ function transformOne(trace, state) {
172152
styleLookup[styles[i].target] = styles[i].value;
173153
}
174154

175-
for(i = 0; i < groupNames.length; i++) {
176-
var groupName = groupNames[i];
177-
178-
var newTrace = newData[i] = Lib.extendDeepNoArrays({}, trace);
179-
180-
cloneTransforms(newTrace);
155+
var newDataByGroup = {};
181156

182-
arrayAttrs.forEach(initializeArray.bind(null, newTrace));
157+
for(i = 0; i < groupNames.length; i++) {
158+
groupName = groupNames[i];
183159

184-
for(j = 0; j < len; j++) {
185-
if(groups[j] !== groupName) continue;
160+
// Start with a deep extend that just copies array references.
161+
newTrace = newData[i] = newDataByGroup[groupName] = Lib.extendDeepNoArrays({}, trace);
162+
newTrace.name = groupName;
186163

187-
arrayAttrs.forEach(pasteArray.bind(null, newTrace, trace, j));
164+
// In order for groups to apply correctly to other transform data (e.g.
165+
// a filter transform), we have to break the connection and clone the
166+
// transforms so that each group writes grouped values into a different
167+
// destination. This function does not break the array reference
168+
// connection between the split transforms it creates. That's handled in
169+
// initialize, which creates a new empty array for each arrayAttr.
170+
transforms = newTrace.transforms;
171+
newTrace.transforms = [];
172+
for(j = 0; j < transforms.length; j++) {
173+
newTrace.transforms[j] = Lib.extendDeepNoArrays({}, transforms[j]);
188174
}
189175

190-
newTrace.name = groupName;
176+
// Initialize empty arrays for the arrayAttrs, to be split in the next step
177+
for(j = 0; j < arrayAttrs.length; j++) {
178+
Lib.nestedProperty(newTrace, arrayAttrs[j]).set([]);
179+
}
191180

192181
Plots.clearExpandedTraceDefaultColors(newTrace);
193182

@@ -196,5 +185,21 @@ function transformOne(trace, state) {
196185
newTrace = Lib.extendDeepNoArrays(newTrace, styleLookup[groupName] || {});
197186
}
198187

188+
189+
// For each array attribute including those nested inside this and other
190+
// transforms (small note that we technically only need to do this for
191+
// transforms that have not yet been applied):
192+
for(k = 0; k < arrayAttrs.length; k++) {
193+
attr = arrayAttrs[k];
194+
195+
// Get the input data:
196+
srcArray = Lib.nestedProperty(trace, attr).get();
197+
198+
// And push each value onto the appropriate destination for this group:
199+
for(j = 0; j < len; j++) {
200+
Lib.nestedProperty(newDataByGroup[groups[j]], attr).get().push(srcArray[j]);
201+
}
202+
}
203+
199204
return newData;
200205
}

0 commit comments

Comments
 (0)