@@ -15,30 +15,84 @@ export const pivot = (
1515 values ,
1616 aggFunc = ( arr ) => arr [ 0 ] ,
1717) => {
18- if ( ! df . columns . includes ( index ) ) {
19- throw new Error ( `Index column '${ index } ' not found` ) ;
18+ // Handle array of index columns
19+ const indexCols = Array . isArray ( index ) ? index : [ index ] ;
20+ // Handle array of column columns
21+ const columnsCols = Array . isArray ( columns ) ? columns : [ columns ] ;
22+
23+ // Check that all index columns exist
24+ for ( const col of indexCols ) {
25+ if ( ! df . columns . includes ( col ) ) {
26+ throw new Error ( `Index column '${ col } ' not found` ) ;
27+ }
2028 }
21- if ( ! df . columns . includes ( columns ) ) {
22- throw new Error ( `Columns column '${ columns } ' not found` ) ;
29+
30+ // Check that all columns columns exist
31+ for ( const col of columnsCols ) {
32+ if ( ! df . columns . includes ( col ) ) {
33+ throw new Error ( `Columns column '${ col } ' not found` ) ;
34+ }
2335 }
36+
37+ // Check that values column exists
2438 if ( ! df . columns . includes ( values ) ) {
2539 throw new Error ( `Values column '${ values } ' not found` ) ;
2640 }
2741
2842 // Convert DataFrame to array of rows
2943 const rows = df . toArray ( ) ;
3044
31- // Get unique values for the index and columns
32- const uniqueIndices = [ ...new Set ( rows . map ( ( row ) => row [ index ] ) ) ] ;
33- const uniqueColumns = [ ...new Set ( rows . map ( ( row ) => row [ columns ] ) ) ] ;
45+ // Get unique values for the index
46+ const uniqueIndices = [ ] ;
47+ if ( indexCols . length === 1 ) {
48+ // Single index column
49+ uniqueIndices . push ( ...new Set ( rows . map ( ( row ) => row [ indexCols [ 0 ] ] ) ) ) ;
50+ } else {
51+ // Multiple index columns - create composite keys
52+ const indexKeys = new Set ( ) ;
53+ rows . forEach ( ( row ) => {
54+ const key = indexCols . map ( ( col ) => row [ col ] ) . join ( '|' ) ;
55+ indexKeys . add ( key ) ;
56+ } ) ;
57+ uniqueIndices . push ( ...indexKeys ) ;
58+ }
59+
60+ // Get unique values for the columns
61+ const uniqueColumns = [ ] ;
62+ if ( columnsCols . length === 1 ) {
63+ // Single column column
64+ uniqueColumns . push ( ...new Set ( rows . map ( ( row ) => row [ columnsCols [ 0 ] ] ) ) ) ;
65+ } else {
66+ // Multiple column columns - create composite keys
67+ const columnKeys = new Set ( ) ;
68+ rows . forEach ( ( row ) => {
69+ const key = columnsCols . map ( ( col ) => row [ col ] ) . join ( '.' ) ;
70+ columnKeys . add ( key ) ;
71+ } ) ;
72+ uniqueColumns . push ( ...columnKeys ) ;
73+ }
3474
3575 // Create a map to store values
3676 const valueMap = new Map ( ) ;
3777
3878 // Group values by index and column
3979 for ( const row of rows ) {
40- const indexValue = row [ index ] ;
41- const columnValue = row [ columns ] ;
80+ // Get index value (single or composite)
81+ let indexValue ;
82+ if ( indexCols . length === 1 ) {
83+ indexValue = row [ indexCols [ 0 ] ] ;
84+ } else {
85+ indexValue = indexCols . map ( ( col ) => row [ col ] ) . join ( '|' ) ;
86+ }
87+
88+ // Get column value (single or composite)
89+ let columnValue ;
90+ if ( columnsCols . length === 1 ) {
91+ columnValue = row [ columnsCols [ 0 ] ] ;
92+ } else {
93+ columnValue = columnsCols . map ( ( col ) => row [ col ] ) . join ( '.' ) ;
94+ }
95+
4296 const value = row [ values ] ;
4397
4498 const key = `${ indexValue } |${ columnValue } ` ;
@@ -50,8 +104,20 @@ export const pivot = (
50104
51105 // Create new pivoted rows
52106 const pivotedRows = uniqueIndices . map ( ( indexValue ) => {
53- const newRow = { [ index ] : indexValue } ;
107+ const newRow = { } ;
54108
109+ // Set index column(s)
110+ if ( indexCols . length === 1 ) {
111+ newRow [ indexCols [ 0 ] ] = indexValue ;
112+ } else {
113+ // Split composite index back into individual columns
114+ const indexParts = indexValue . split ( '|' ) ;
115+ indexCols . forEach ( ( col , i ) => {
116+ newRow [ col ] = indexParts [ i ] ;
117+ } ) ;
118+ }
119+
120+ // Set value columns
55121 for ( const columnValue of uniqueColumns ) {
56122 const key = `${ indexValue } |${ columnValue } ` ;
57123 const values = valueMap . get ( key ) || [ ] ;
@@ -70,7 +136,22 @@ export const pivot = (
70136 * @param {Class } DataFrame - DataFrame class to extend
71137 */
72138export const register = ( DataFrame ) => {
73- DataFrame . prototype . pivot = function ( index , columns , values , aggFunc ) {
139+ DataFrame . prototype . pivot = function ( index , columns , values , aggFunc ) {
140+ // Support for object parameter style
141+ if (
142+ typeof index === 'object' &&
143+ index !== null &&
144+ ! ( index instanceof Array )
145+ ) {
146+ const options = index ;
147+ return pivot (
148+ this ,
149+ options . index ,
150+ options . columns ,
151+ options . values ,
152+ options . aggFunc ,
153+ ) ;
154+ }
74155 return pivot ( this , index , columns , values , aggFunc ) ;
75156 } ;
76157} ;
0 commit comments