How to avoid warning when introducing NAs by coercion
Asked Answered
J

5

145

I generally prefer to code R so that I don't get warnings, but I don't know how to avoid getting a warning when using as.numeric to convert a character vector.

For example:

x <- as.numeric(c("1", "2", "X"))

Will give me a warning because it introduced NAs by coercion. I want NAs introduced by coercion - is there a way to tell it "yes this is what I want to do". Or should I just live with the warning?

Or should I be using a different function for this task?

Janie answered 20/2, 2013 at 16:31 Comment(5)
See ?suppressWarnings perhaps?Mazman
What is the problem with this warning? Generally it gives valuable information. I prefer a more verbose output in the R console to nasty surprises.Hindenburg
@Hindenburg I totally agree, but the usefulness of warnings diminishes if you get used to just ignoring them. That's why I generally like to "tackle" the warnings. In this case, I will ALWAYS generate warnings, and lots of them - my data is coming in as strings with "X" representing NA, and so the function is doing exactly what I want it to do. I wanted to says "Thanks for letting me know, but it's ok I know what I'm doing". suppressWarnings seems perfect.Janie
You know that read.table accepts an argument na.strings?Hindenburg
It's useful to suppress them if you already have a work around to a known bug in a library. That's how I'm going to use this!Detumescence
F
164

Use suppressWarnings():

suppressWarnings(as.numeric(c("1", "2", "X")))
[1]  1  2 NA

This suppresses warnings.

Faviolafavonian answered 20/2, 2013 at 16:38 Comment(1)
Although this is the preferred response, the answer by jangorecki below seems, to me, more solid.Turenne
L
40

In general suppressing warnings is not the best solution as you may want to be warned when some unexpected input will be provided.
Solution below is wrapper for maintaining just NA during data type conversion. Doesn't require any package.

    as.num = function(x, na.strings = "NA") {
        stopifnot(is.character(x))
        na = x %in% na.strings
        x[na] = "0"
        x = as.numeric(x)
        x[na] = NA_real_
        x
    }
    as.num(c("1", "2", "X"), na.strings="X")
    #[1]  1  2 NA
Larsen answered 26/3, 2016 at 19:12 Comment(2)
This is the best answer. Using suppressWarnings() is generally a bad idea, because we sometimes need to see those warnings.Cataract
This is nice, but it only works for known patterns.Portraitist
E
39

suppressWarnings() has already been mentioned. An alternative is to manually convert the problematic characters to NA first. For your particular problem, taRifx::destring does just that. This way if you get some other, unexpected warning out of your function, it won't be suppressed.

> library(taRifx)
> x <- as.numeric(c("1", "2", "X"))
Warning message:
NAs introduced by coercion 
> y <- destring(c("1", "2", "X"))
> y
[1]  1  2 NA
> x
[1]  1  2 NA
Erdah answered 20/2, 2013 at 16:42 Comment(3)
I know this is an old thread and destring works perfectly for op's example, but one caveat for anyone who sees this thread in the future is that destring works differently from as.numeric when the target string is a mixture of string and numeric : that is, destring("x1") gives 1 but as.numeric("x1") gives NAAdamandeve
Error in library(taRifx): there is no package called ‘taRifx’ There is only Zuul. knowyourmeme.com/memes/there-is-no-dana-only-zuulOrangery
package: taRifx has been archived on CRAN so this answer is no long relevantUniversality
Z
1

I have slightly modified the jangorecki function for the case where we may have a variety of values that cannot be converted to a number. In my function, a template search is performed and if the template is not found, FALSE is returned.! before gperl, it means that we need those vector elements that do not match the template. The rest is similar to the as.num function. Example:

as.num.pattern <- function(x, pattern){
  stopifnot(is.character(x))
  na = !grepl(pattern, x)
  x[na] = -Inf
  x = as.numeric(x)
  x[na] = NA_real_
  x
}

as.num.pattern(c('1', '2', '3.43', 'char1', 'test2', 'other3', '23/40', '23, 54 cm.'))

[1] 1.00 2.00 3.43   NA   NA   NA   NA   NA
Zoogloea answered 7/7, 2020 at 8:56 Comment(1)
The example will not run presently because pattern has not been specified. as.num.pattern(c('1', '2', '3.43', NA, 'char1', 'test2', 'other3', '23/40', '23, 54 cm.'),pattern = "^[0-9\\.,]+$") will reproduce the results.Overriding
L
0

One way to silence only particular warnings is to use the approach at Suppress warning based on their position in warning list or based on a regular expression in R

EDIT: Note that this approach is not robust to locale changes/translations (thanks to Ben Bolker for pointing this out).

Here's a full example for the specific OP's case:

with_warning_handler <- function(reg, ...)
{
  withCallingHandlers(..., warning = function(w)
    {
        condition <- conditionMessage(w)
        if(grepl(reg, condition)) invokeRestart("muffleWarning")
  })
}


with_warning_handler("NAs introduced by coercion",
  x <- as.numeric(c("1", "2", "X"))
)
Lachrymose answered 14/7, 2023 at 14:6 Comment(2)
This isn't robust to locale changes/translation of warning messages into other languages.Portraitist
@BenBolker Good point! Thank you. I edited to add in that concern.Lachrymose

© 2022 - 2025 — McMap. All rights reserved.