24

I have these three strings:

letters <- "abc" 
numbers <- "123" 
mix <- "b1dd"

How can I check which one of these strings contains LETTERS ONLY or NUMBERS ONLY (in R)?

letters should only be TRUE in the LETTERS ONLY check

numbers should only be TRUE in the NUMBERS ONLY check

mix should be FALSE in every situation

I tried several approaches now but none of them really worked for me :(

For example if I use

grepl("[A-Za-z]", letters) 

It works well for letters, but it would also works for mix, what I don't want.

Thanks in advance.

Felix Grossmann
  • 1,224
  • 1
  • 11
  • 30

3 Answers3

34
# Check that it doesn't match any non-letter
letters_only <- function(x) !grepl("[^A-Za-z]", x)

# Check that it doesn't match any non-number
numbers_only <- function(x) !grepl("\\D", x)

letters <- "abc" 
numbers <- "123" 
mix <- "b1dd"

letters_only(letters)
## [1] TRUE

letters_only(numbers)
## [1] FALSE

letters_only(mix)
## [1] FALSE

numbers_only(letters)
## [1] FALSE

numbers_only(numbers)
## [1] TRUE

numbers_only(mix)
## [1] FALSE
Tim Goodman
  • 23,308
  • 7
  • 64
  • 83
  • 2
    numbers_only does works only for integers. I suggest using `numbers_only <- function(x) suppressWarnings(!is.na(as.numeric(as.character(k))))` if you want to include fractions in the test, as discussed here: https://stackoverflow.com/questions/24129124/how-to-determine-if-a-character-vector-is-a-valid-numeric-or-integer-vector?noredirect=1&lq=1 – Mikko Apr 19 '18 at 09:38
  • @Mikko Yes, I interpreted the request as "Check if every character in the string is a digit." So it wouldn't match fractions, decimals, scientific notation, or even integers with a thousands separator. If one wants to recognize "strings that can represent a number", it becomes culture dependent. E.g., under American cultural conventions a number can contain multiple commas (thousands separators), but only one period (the decimal point), and no spaces. But in many other countries the role of comma and period is reversed, or a space is used as the thousands or millions separator. – Tim Goodman Apr 20 '18 at 18:05
  • Shouldn't this be !grepl("\\d", x)?. The \\D didn't work for me. Thanks. – BICube Mar 28 '19 at 23:18
  • 1
    @BICube `grepl("\\D", x)` will match if `x` contains any non-digit. (Capital D for non-digit). And so, `!grepl("\\D", x)` will match if `x` _doesn't_ contain any non-digit -- i.e., if `x` contains _only_ digits. (Whereas, `!grepl("\\d", x)` will match if `x` contains _no_ digits.) – Tim Goodman Mar 29 '19 at 01:49
18

you need to persist your regex

all_num <- "123"
all_letters <- "abc"
mixed <- "123abc"


grepl("^[A-Za-z]+$", all_num, perl = T) #will be false
grepl("^[A-Za-z]+$", all_letters, perl = T) #will be true
grepl("^[A-Za-z]+$", mixed, perl=T) #will be false
Tonio Liebrand
  • 17,189
  • 4
  • 39
  • 59
Mike Tung
  • 4,735
  • 1
  • 17
  • 24
5

Using the stringr package

library(stringr)
all_num <- "123"
all_letters <- "abc"
mixed <- "123abc"

# LETTERS ONLY
str_detect(all_num, "^[:alpha:]+$")
str_detect(all_letters, "^[:alpha:]+$")
str_detect(mixed, "^[:alpha:]+$")

# NUMBERS ONLY
str_detect(all_num, "^[:digit:]+$")
str_detect(all_letters, "^[:digit:]+$")
str_detect(mixed, "^[:digit:]+$")
Jeff Parker
  • 1,809
  • 1
  • 18
  • 28