TypeError: not supported between instances of str and float in Pandas
Use pd.to_numeric(df['col'], errors='coerce') to convert corrupted or mixed string columns into numeric float types before sorting or filtering.
Root Cause Analysis
This error occurs when Python tries to sort, filter, or compare values in a pandas DataFrame column, but the column contains mixed data types with both string and float instances that have no defined ordering.
Cause 1: Ingestion of Mixed-Type Columns (Object Dtype)
When loading CSV data where numerical columns contain placeholder strings (such as 'N/A', 'missing', or '-'), pandas defaults the column dtype to object. When evaluating comparisons like df['col'] > 10 or calling df.sort_values('col'), Python attempts to compare str directly against float, triggering TypeError: '<' not supported between instances of 'str' and 'float'.
Cause 2: Difference Between np.nan and String 'nan'
np.nan is typed as float in Python and NumPy. A column containing np.nan will be inferred as float64 — but a column containing the string 'nan' remains object dtype. They look identical when printed but are different types.
Cause 3: Concatenation of Unaligned DataFrames
Concatenating datasets where one file stores a column as numeric and another stores it as string results in a combined object column with mixed runtime types.
Reproduction Code (MCVE)
import pandas as pd
df = pd.DataFrame({'rating': [4.5, 'N/A', 3.8, 4.9]})
# Sorting mixed object column triggers TypeError
df.sort_values('rating')
Solution 1: Coerce Non-Numeric Strings with pd.to_numeric()
Convert the column with pd.to_numeric(errors='coerce'), which turns unparseable string placeholders into NaN while preserving valid numeric floats.
import pandas as pd
df = pd.DataFrame({'rating': [4.5, 'N/A', 3.8, 4.9]})
# Coerce unparseable strings to NaN
df['rating'] = pd.to_numeric(df['rating'], errors='coerce')
# Now sorting works cleanly
sorted_df = df.sort_values('rating')
print(sorted_df)
Solution 2: Quarantine Invalid Rows Before Processing
Identify and isolate non-numeric records into a separate review DataFrame before proceeding with numerical calculations.
import pandas as pd
df = pd.DataFrame({'rating': [4.5, 'N/A', 3.8, 4.9]})
numeric_series = pd.to_numeric(df['rating'], errors='coerce')
# Separate clean data from invalid entries
invalid_rows = df[numeric_series.isna()]
clean_df = df[numeric_series.notna()].copy()
clean_df['rating'] = numeric_series[numeric_series.notna()]
print(f'Clean records count: {len(clean_df)}')
print(f'Quarantined records: {len(invalid_rows)}')
Common Mistakes & Edge Cases
1. Performance Impact of Object Dtype
Operations on a float64 column are fully vectorised by NumPy and can be 10 to 100x faster than equivalent operations on an object column, which falls back to element-by-element Python iteration.
2. Contrasting TypeError vs ValueError
Sorting mixed types raises TypeError because ordering is undefined. In contrast, calling int('4.5') raises ValueError because the decimal point is invalid in an integer parser.
3. Locale-Specific Decimal Formatting
In European datasets, decimal numbers often use commas ('12,5'). pd.to_numeric() will coerce these to NaN unless commas are replaced with dots: df['col'].astype(str).str.replace(',', '.').pipe(pd.to_numeric, errors='coerce').