Type & Coercion Errors

Non-numeric argument to operator

Matches: non-numeric argument to binary operator

WHAT THIS ERROR MEANS

You tried to do math (like +, -, *, /) on something that isn't a number, such as a character string or factor.

WHY IT HAPPENS — 4 COMMON CAUSES

1. A numeric column imported as text

One stray non-numeric value anywhere in a column — "N/A", "n/a", "-", a footnote marker, or a thousands separator — forces the whole column to character on import. The other 9,999 values look like numbers but the column’s type is character.

2. Currency symbols, commas or percent signs

"$1,234.56" and "12%" are strings. Financial extracts routinely carry these, and as.numeric() on them returns NA with a coercion warning rather than the value you wanted.

3. The value is a factor

Factors are integer codes with labels. Arithmetic on them either errors or, worse, silently operates on the codes — as.numeric() on a factor of years returns 1, 2, 3 rather than 2021, 2022, 2023.

4. You are operating on a data frame rather than a column

df * 2 fails when df has any non-numeric column, because the operation applies to the whole frame. df$amount * 2 targets one column.

HOW TO DIAGNOSE WHICH ONE IT IS

  1. Run str(df) or glimpse(df) to see every column’s type at once — the fastest way to spot a chr column that should be num.
  2. For one column, class(df$amount) gives the answer directly.
  3. Find the offending values: df$amount[is.na(as.numeric(df$amount))] lists everything that will not convert.
  4. Check for hidden whitespace with unique(df$amount) on a small sample.
  5. If it is a factor, confirm with is.factor() before converting — the conversion route is different.

HOW TO FIX IT

1. Check the types of your variables with class() or str().

2. Convert to numeric with as.numeric() if appropriate.

3. Make sure you're referencing the right column.

CODE EXAMPLES

BAD — THIS CAUSES THE ERROR
"10" + 5  # "10" is a string, not a number
GOOD — CORRECT APPROACH
as.numeric("10") + 5

MORE SCENARIOS THAT TRIGGER THIS

Currency strings from a finance export

BAD
df$amount <- c("$1,200.50", "$980.00")
sum(df$amount)
# Error: invalid 'type' (character) of argument
GOOD
df$amount <- as.numeric(gsub("[$,]", "", df$amount))
sum(df$amount)

# or with readr, which handles this directly:
df$amount <- readr::parse_number(df$amount)

parse_number() strips currency symbols, thousands separators and trailing text in one call, and reports how many values failed rather than silently producing NA.

Converting a factor of numbers

BAD
years <- factor(c("2021", "2022", "2023"))
as.numeric(years)
# returns 1 2 3 — the integer codes, not the years
GOOD
as.numeric(as.character(years))
# returns 2021 2022 2023

This one is dangerous because it does not error — it returns plausible small integers. Always route factors through as.character() before as.numeric().

PACKAGE-SPECIFIC NOTES

readr is stricter and more informative than base read.csv(): it guesses column types from the first 1,000 rows and prints a problems() report when later rows contradict the guess, which surfaces exactly the stray "N/A" that would otherwise turn a numeric column to text. You can force types with col_types = cols(amount = col_double()). data.table::fread() is similarly good at this. In base R, read.csv(na.strings = c("NA", "N/A", "-", "")) tells the parser which markers mean missing so the column still comes in numeric.

FUNCTIONS WORTH KNOWING

class()str()as.numeric()readr::parse_number()gsub()is.na()type.convert()

FREQUENTLY ASKED QUESTIONS

Why does as.numeric() give NAs and a warning instead of an error?

as.numeric() converts what it can and returns NA for the rest, warning once about the coercion. That is deliberate — it lets you convert a mostly-clean column and then inspect the failures — but it means silent data loss if you ignore the warning. Check sum(is.na(result)) afterwards.

How do I find which rows are the problem?

df[is.na(as.numeric(df$amount)) & !is.na(df$amount), ] returns the rows whose values are present but unconvertible, which is normally a short and very informative list.

Why does sum() fail when mean() on the same column worked?

It generally does not — but if the column is a factor, some functions dispatch to a method that errors while others operate on the integer codes and return a meaningless number. Check the class before trusting either result.

Still stuck?

Paste your code in RChat and the AI will fix this error in context.

Try RChat Free →

RELATED TYPE & COERCION ERRORS