@@ -143,25 +143,28 @@ def clean_data(
143143 df = df .dropna (how = "all" )
144144 logger .info (f"Dropped all-null rows → { len (df ):,} rows remaining" )
145145
146- # 3. Strip whitespace from strings
147- # NOTE: We use a value-level map instead of col.str.strip() to avoid
148- # silently converting non-string values (e.g. ints in object columns)
149- # to NaN. Only actual str instances are stripped; all other types are
150- # left untouched.
151- if config .get ("strip_strings" , True ):
152- obj_cols = _cat_cols (df )
153- df [obj_cols ] = df [obj_cols ].apply (
154- lambda col : col .map (lambda v : v .strip () if isinstance (v , str ) else v )
155- )
156- logger .debug (f"Stripped whitespace from { len (obj_cols )} string columns" )
157-
158- # 4. Lowercase string columns
159- # Same rationale: apply lower() only to actual str values.
160- if config .get ("lowercase_strings" , False ):
146+ # 3 & 4. String cleaning (strip whitespace / lowercase)
147+ # NOTE: We use value-level transformation to preserve non-string types
148+ # (e.g. ints/floats in object columns) without coercing to NaN.
149+ do_strip = config .get ("strip_strings" , True )
150+ do_lower = config .get ("lowercase_strings" , False )
151+
152+ if do_strip or do_lower :
161153 obj_cols = _cat_cols (df )
162- df [obj_cols ] = df [obj_cols ].apply (
163- lambda col : col .map (lambda v : v .lower () if isinstance (v , str ) else v )
164- )
154+ if obj_cols :
155+ def _clean_val (v ):
156+ if isinstance (v , str ):
157+ if do_strip :
158+ v = v .strip ()
159+ if do_lower :
160+ v = v .lower ()
161+ return v
162+
163+ df [obj_cols ] = df [obj_cols ].apply (lambda col : col .map (_clean_val ))
164+ if do_strip :
165+ logger .debug (f"Stripped whitespace from { len (obj_cols )} string columns" )
166+ if do_lower :
167+ logger .debug (f"Lowercased { len (obj_cols )} string columns" )
165168
166169 # 5. Drop duplicates
167170 if config .get ("drop_duplicates" , True ):
0 commit comments