R: regex for extracting non-numeric entries from a character vector of numbers

Viewed 459

I have a data.frame in which one column of numeric data is read by readr as character, at least in part because some of the values are "N/A". I don't know if the values actually include quotation marks.

I am trying to extract all the values in that column that contain things other than pure numbers, i.e. which contain a any character which not a number, 1-9. My purpose is to learn how many of these there are and to see if there are any formats besides the "N/A", in preparation for replacing them with something else and then converting the vector to numeric.

While I am confident that there are smarter ways to do this, I am trying to extract those values with a logical vector created from a regex applied to to the vector using R's grepl command.

A2 <- 1:10
A3 <- sample(1000:9999, 10)

dat_df <- data.frame(A2, A3)
str(dat_df)
dat_df$A3[1:3]<- c("N/A", "", "banana")

dat_df is a simplified data set, provided for reproducibility.

Here is an example

dat_df$A3[grepl(as.character(\<\d*[a-zA-Z][a-zA-Z0-9]*>\), x = dat_df$A3)]

This particular one gives the error

Error: unexpected '<' in dat_df"$A3[grepl(as.character(\<"

I have tried a lot of varients of this. These include: Wrapping the initial data in ( ) (in case it was a precedence problem). Defining the regex as a character string using as.character as the help file recommends, or with quotation marks. Wrapping the central portion of the regex with ^ and $ instead of \< and >\ Doubling all the "\"s

In every case I get some variant of the syntax error shown above, varying with the version.

Error: unexpected (and then)
  • '^' if it starts with a '^'
  • '\' if it starts with a '\'
  • '<' if it starts with a '<'
  • '\d' if it is wrapped in quotation marks instead of using as.character

I can not make heads or tails out of this pattern of errors.

Any help gratefully received and acknowledged.

1 Answers

Firstly, as.character(\<\d*[a-zA-Z][a-zA-Z0-9]*>\) is incorrect and doesn't work. For example, as.character(A) doesn't give you "A" but gives an error. You should enclose the pattern with quotes.

Secondly, in R regex you need to use double backslash to escape. So \\ instead of \.

If you only have integer data you can use grep with invert = TRUE and value = TRUE to get the values which are not numbers.

grep('^\\d+$', dat_df$A3, invert = TRUE, value = TRUE)
#[1] "N/A"    ""       "banana"

To change these values to NA and turn them to numeric you may do -

dat_df$A3[grep('^\\d+$', dat_df$A3, invert = TRUE)] <- NA
dat_df$A3 <- as.numeric(dat_df$A3)
dat_df

#   A2   A3
#1   1   NA
#2   2   NA
#3   3   NA
#4   4 7475
#5   5 1162
#6   6 9828
#7   7 6359
#8   8 7823
#9   9 2544
#10 10 5287

You can also use grepl to do the same if you prefer that over grep but it doesn't have value and invert argument so might need to change few small things to make it work.

Related