@@ -248,18 +248,19 @@ export function computePivot<T extends Record<string, unknown>>({
248248 // Apply filter first if provided
249249 const filteredData = filter ? data . filter ( filter ) : data ;
250250
251- // Filter out records that do not have defined values for all rowFields.
252- // This avoids creating a row key of "undefined" and ensures such records
253- // are not returned as part of the cells/row totals.
254- const dataWithDefinedRows = filteredData . filter ( ( rec ) =>
255- rowFields . every ( ( f ) => rec [ f ] !== undefined )
251+ // Filter out records that do not have defined values for all rowFields and columnFields.
252+ // This avoids creating a row or column key of "undefined" and ensures such records
253+ // are not returned as part of the cells/totals.
254+ const dataWithDefinedKeys = filteredData . filter ( ( rec ) =>
255+ rowFields . every ( ( f ) => rec [ f ] !== undefined ) &&
256+ columnFields . every ( ( f ) => rec [ f ] !== undefined )
256257 ) ;
257258 const rowKeyTuples : unknown [ ] [ ] = [ ] ;
258259 const rowKeySet = new Set < string > ( ) ;
259260 const colKeyTuples : unknown [ ] [ ] = [ ] ;
260261 const colKeySet = new Set < string > ( ) ;
261262
262- for ( const rec of dataWithDefinedRows ) {
263+ for ( const rec of dataWithDefinedKeys ) {
263264 const rTuple = getTuple ( rec , rowFields ) ;
264265 const rKey = toKey ( rTuple ) ;
265266 if ( ! rowKeySet . has ( rKey ) ) {
@@ -295,7 +296,7 @@ export function computePivot<T extends Record<string, unknown>>({
295296
296297 // Partition records per cell
297298 const cellRecords : Record < string , Record < string , T [ ] > > = { } ;
298- for ( const rec of dataWithDefinedRows ) {
299+ for ( const rec of dataWithDefinedKeys ) {
299300 const rKey = toKey ( getTuple ( rec , rowFields ) ) ;
300301 const cKey = toKey ( getTuple ( rec , columnFields ) ) ;
301302 if ( ! cellRecords [ rKey ] ) cellRecords [ rKey ] = { } ;
@@ -315,10 +316,27 @@ export function computePivot<T extends Record<string, unknown>>({
315316 }
316317 const value = aggregate ( values , records , aggregator ) ;
317318 cells [ rKey ] [ cKey ] = { value, records } ;
318- rowTotals [ rKey ] += value ;
319319 }
320320 }
321321
322+ // Calculate row totals using the same aggregation method applied over all records in the row
323+ for ( const rKey of Object . keys ( cells ) ) {
324+ const rowRecords : T [ ] = [ ] ;
325+ const rowValues : number [ ] = [ ] ;
326+ const cols = cellRecords [ rKey ] ?? { } ;
327+ for ( const cKey of Object . keys ( cols ) ) {
328+ const records = cols [ cKey ] ;
329+ rowRecords . push ( ...records ) ;
330+ if ( valueField != null ) {
331+ for ( const rec of records ) {
332+ const v = getNumber ( rec [ valueField ] ) ;
333+ if ( v != null ) rowValues . push ( v ) ;
334+ }
335+ }
336+ }
337+ rowTotals [ rKey ] = aggregate ( rowValues , rowRecords , aggregator ) ;
338+ }
339+
322340 // Calculate column totals using the same aggregation method
323341 for ( const cKey of Object . keys ( colTotals ) ) {
324342 const columnRecords : T [ ] = [ ] ;
@@ -344,7 +362,7 @@ export function computePivot<T extends Record<string, unknown>>({
344362 // non-additive aggregations like "avg").
345363 let grandTotal : number ;
346364 {
347- const allRecords = dataWithDefinedRows ;
365+ const allRecords = dataWithDefinedKeys ;
348366 const allValues : number [ ] = [ ] ;
349367 if ( valueField != null ) {
350368 for ( const rec of allRecords ) {
0 commit comments