11import { Series } from '../../../core/dataframe/Series.js' ;
2- import { VectorFactory } from '../../../core/storage/VectorFactory.js' ;
32
43/**
54 * Creates new columns or modifies existing columns in a DataFrame by applying functions to each row
@@ -18,35 +17,50 @@ export function mutate(df, columnFunctions, options = {}) {
1817 throw new Error ( 'Column functions must be specified as an object' ) ;
1918 }
2019
21- // Get row count
20+ // Get row count and columns for processing
2221 const rowCount = df . rowCount ;
22+ const columns = df . columns ;
2323
24- // Convert DataFrame to array of row objects for processing
25- const rows = df . toArray ( ) ;
24+ // Process column functions and create new column arrays
25+ const newColumns = { } ;
2626
27- // If inplace=true, modify DataFrame directly
28- if ( inplace ) {
29- // Apply mutation functions to each column
30- for ( const [ colName , colFunc ] of Object . entries ( columnFunctions ) ) {
31- if ( typeof colFunc !== 'function' ) {
32- throw new Error ( `Value for column '${ colName } ' must be a function` ) ;
33- }
27+ // For each column function
28+ for ( const [ colName , colFunc ] of Object . entries ( columnFunctions ) ) {
29+ if ( typeof colFunc !== 'function' ) {
30+ throw new Error ( `Value for column '${ colName } ' must be a function` ) ;
31+ }
32+
33+ // Create array for new column values
34+ const colValues = new Array ( rowCount ) ;
3435
35- // Create new column by applying function to each row
36- const values = [ ] ;
36+ // Process each row
37+ for ( let i = 0 ; i < rowCount ; i ++ ) {
38+ // Build row object for this index
39+ const row = { } ;
40+ for ( const col of columns ) {
41+ row [ col ] = df . col ( col ) . get ( i ) ;
42+ }
3743
38- // Process each row
39- for ( let i = 0 ; i < rowCount ; i ++ ) {
40- // Apply the transformation function with correct parameters
41- const result = colFunc ( rows [ i ] , i , df ) ;
44+ // Apply the transformation function with correct parameters
45+ let result = colFunc ( row , i , df ) ;
4246
43- // Convert null/undefined to NaN
44- values . push ( result === null || result === undefined ? NaN : result ) ;
47+ // Convert null/undefined to NaN
48+ if ( result === null || result === undefined ) {
49+ result = NaN ;
4550 }
4651
47- // Create new Series for this column
48- const vector = VectorFactory . from ( values ) ;
49- const series = new Series ( vector , { name : colName } ) ;
52+ colValues [ i ] = result ;
53+ }
54+
55+ // Store the column values
56+ newColumns [ colName ] = colValues ;
57+ }
58+
59+ if ( inplace ) {
60+ // Update existing columns and add new ones
61+ for ( const [ colName , colValues ] of Object . entries ( newColumns ) ) {
62+ // Create a new Series for this column
63+ const series = new Series ( colValues , { name : colName } ) ;
5064
5165 // Update or add Series to DataFrame
5266 df . _columns [ colName ] = series ;
@@ -62,36 +76,27 @@ export function mutate(df, columnFunctions, options = {}) {
6276 // Return the original DataFrame
6377 return df ;
6478 } else {
65- // Create a new object to store all columns
79+ // Create a new DataFrame with all columns
6680 const newData = { } ;
6781
68- // Copy existing columns
69- for ( const col of df . columns ) {
70- newData [ col ] = df . col ( col ) . toArray ( ) ;
71- }
72-
73- // Apply mutation functions to each column
74- for ( const [ colName , colFunc ] of Object . entries ( columnFunctions ) ) {
75- if ( typeof colFunc !== 'function' ) {
76- throw new Error ( `Value for column '${ colName } ' must be a function` ) ;
82+ // Copy existing columns that aren't being modified
83+ for ( const col of columns ) {
84+ if ( ! ( col in newColumns ) ) {
85+ newData [ col ] = df . col ( col ) . toArray ( ) ;
86+ } else {
87+ // Use the new values for modified columns
88+ newData [ col ] = newColumns [ col ] ;
7789 }
90+ }
7891
79- // Create new column
80- newData [ colName ] = [ ] ;
81-
82- // Process each row
83- for ( let i = 0 ; i < rowCount ; i ++ ) {
84- // Apply the transformation function with correct parameters
85- const result = colFunc ( rows [ i ] , i , df ) ;
86-
87- // Convert null/undefined to NaN
88- newData [ colName ] . push (
89- result === null || result === undefined ? NaN : result ,
90- ) ;
92+ // Add completely new columns
93+ for ( const colName of Object . keys ( newColumns ) ) {
94+ if ( ! columns . includes ( colName ) ) {
95+ newData [ colName ] = newColumns [ colName ] ;
9196 }
9297 }
9398
94- // Create a new DataFrame with updated data
99+ // Create a new DataFrame with the updated data
95100 return new df . constructor ( newData ) ;
96101 }
97102}
0 commit comments