Sythra

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.

vaibhavkothari· Aug 26, 2026· 6 min readBeginner
ShareXLinkedIn
ValueError: could not convert string to float — fix your data, not your code cover

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 withWhat 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

  1. Read the quoted value in the error — it names the problem
  2. pd.to_numeric(col, errors="coerce") to find every bad row at once
  3. Print .unique() on the bad values to see the real patterns
  4. Strip symbols, then convert
  5. Choose deliberately how to handle NaN — drop, fill, or flag
  6. Add thousands= and na_values= to read_csv so 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.

Next reading on Sythra Articles

Keep reading

Related articles

Newsletter

Get new articles

Free essays on learning, Python, and ML — no account required. We’ll only email when there’s something worth reading.

ValueError: could not convert string to float — fix your data, not your code