Article
ValueError: could not convert string to float — fix your data, not your code
This error means one cell in your data is not a number. Learn how to find the exact bad row in pandas and clean commas, currency symbols, percent signs and blanks for good.
On this page0%
- Step 1 — Read the message properly
- Step 2 — Find the guilty rows
- Step 3 — Clean the column
- Step 4 — Decide what to do with the blanks
- Step 5 — Fix the same error in scikit-learn
- Step 6 — Stop it happening on the next file
- The checklist
- FAQ
- What causes ValueError: could not convert string to float?
- How do I find which row causes the error in pandas?
- How do I convert a column with commas to float?
- Should I fill missing numbers with zero?
- Why does scikit-learn raise this error during fit?
- Next reading on Sythra Articles
ValueError: could not convert string to float: '1,250'
Python is telling you exactly what it choked on — look at the text in quotes at the end of the message. That is a real value from your data. In this case a thousands separator: 1,250 is a number to a human, and a string to Python.
This error is almost never a coding mistake. It is a data mistake, and the fastest fix is to find the bad rows first and clean them deliberately.
Step 1 — Read the message properly
The value after the colon is your entire clue:
| Message ends with | What is in your data |
|---|---|
: '1,250' | Thousands separator |
: '$45.00' | Currency symbol |
: '12%' | Percent sign |
: '' | Empty cell |
: 'N/A' or : '-' | Placeholder for missing |
: '12.5 kg' | Unit stuck to the number |
: '1.234,56' | European decimal format |
If the message ends with : '', the cell is blank — the most common case of all when a CSV was exported from a spreadsheet.
Step 2 — Find the guilty rows
Do not scroll through the file. Ask pandas which values fail to convert:
import pandas as pd
df = pd.read_csv("sales.csv")
# to_numeric with errors="coerce" turns anything unconvertible into NaN
converted = pd.to_numeric(df["price"], errors="coerce")
bad_rows = df[converted.isna() & df["price"].notna()]
print(bad_rows[["price"]].head(20))
print("Bad values:", bad_rows["price"].unique()[:20])
That last line is the useful one. It prints the distinct offenders — usually three or four patterns, not three thousand unique problems. Now you know exactly what to clean.
Step 3 — Clean the column
Strip the junk, then convert. Chain the replacements so the intent stays readable:
df["price"] = (
df["price"]
.astype(str)
.str.strip() # stray spaces
.str.replace(",", "", regex=False) # thousands separator
.str.replace("$", "", regex=False) # currency
.str.replace("%", "", regex=False) # percent
)
df["price"] = pd.to_numeric(df["price"], errors="coerce")
A more general version strips every character that is not a digit, dot, or minus sign:
df["price"] = (
df["price"].astype(str).str.replace(r"[^0-9.\-]", "", regex=True)
)
df["price"] = pd.to_numeric(df["price"], errors="coerce")
Careful with percentages: after removing %, the value 12 means 0.12. Divide explicitly so nobody has to guess later:
df["rate"] = pd.to_numeric(df["rate"].str.rstrip("%"), errors="coerce") / 100
Step 4 — Decide what to do with the blanks
errors="coerce" converts the unfixable into NaN"Not a Number" — pandas' marker for a missing value. You now have a decision to make, and it matters more than the cleaning itself:
missing = df["price"].isna().sum()
print(f"{missing} missing out of {len(df)} rows")
# Option A — drop rows with no price
df = df.dropna(subset=["price"])
# Option B — fill with the median (robust to outliers)
df["price"] = df["price"].fillna(df["price"].median())
# Option C — keep them and flag it, so a model can learn from "missing"
df["price_missing"] = df["price"].isna().astype(int)
df["price"] = df["price"].fillna(df["price"].median())
Option C is usually the strongest for machine learning: missing data is often informative. A blank income field may say more than any imputed number would.
Never silently fill with 0. A price of zero is a real, meaningful value, and pretending a missing price is free will quietly poison every model you train afterwards.
Step 5 — Fix the same error in scikit-learn
If the traceback mentions fit, transform, or StandardScaler, the error comes from a text column that slipped into your feature matrix:
print(df.dtypes)
print(df.select_dtypes(include="object").columns.tolist())
Any object column is text as far as scikit-learn is concerned. Categories must be encoded, not converted:
X = pd.get_dummies(df[["price", "city", "category"]], drop_first=True)
One-hot encodingTurning each category into its own 0/1 column via get_dummies gives the model numbers it can use without inventing a fake order. Never map {"low": 1, "medium": 2, "high": 3} unless the order is genuinely real.
Step 6 — Stop it happening on the next file
Tell pandas about your data's quirks while reading it, and the cleaning disappears:
df = pd.read_csv(
"sales.csv",
thousands=",", # handles 1,250
na_values=["", "N/A", "-", "NA", "null", "missing"],
dtype={"zip_code": str}, # keep IDs as text, preserve leading zeros
)
That dtype line prevents the opposite bug: pandas reading a zip code of 07030 as the number 7030.
For European files where . groups and , decimals:
df = pd.read_csv("sales.csv", thousands=".", decimal=",")
The checklist
- Read the quoted value in the error — it names the problem
pd.to_numeric(col, errors="coerce")to find every bad row at once- Print
.unique()on the bad values to see the real patterns - Strip symbols, then convert
- Choose deliberately how to handle NaN — drop, fill, or flag
- Add
thousands=andna_values=toread_csvso the next load is clean
FAQ
What causes ValueError: could not convert string to float?
A value in your data is text that Python cannot parse as a number — typically a comma separator, a currency symbol, a percent sign, a unit, or an empty cell. The offending value is printed at the end of the error message.
How do I find which row causes the error in pandas?
Run pd.to_numeric(df["col"], errors="coerce"), then select rows where the result is NaN but the original was not null. Printing .unique() on those values shows the handful of patterns you actually need to clean.
How do I convert a column with commas to float?
Use df["col"].str.replace(",", "", regex=False) and then pd.to_numeric, or pass thousands="," to read_csv so pandas handles it while loading.
Should I fill missing numbers with zero?
No. Zero is a real value and will distort averages and model training. Use the median, or keep the NaN and add a separate 0/1 column marking that the value was missing.
Why does scikit-learn raise this error during fit?
A text column is still in your feature matrix. Check df.dtypes for object columns and encode them with pd.get_dummies before training.