105

I imagine this is incredibly simple but I cant seem to find the answer.

I am writing an IF statement but the test is if the object returns a character(0) value. I am not sure how to deal with character(0) in the statement.

Assuming Test <- character(0) or a value:

if (identical(Pols4,character(0))) {
  print('Empty')
} else {
  print('Not Empty')
}

It still does not seem to work.....

Rob
  • 834
  • 1
  • 10
  • 15
Methexis
  • 2,739
  • 5
  • 24
  • 34

7 Answers7

127

Use the identical function to check this.

a <- character(0)
identical(a, character(0))  # returns TRUE

identical(a, "")           # returns FALSE
identical(a, numeric(0))   # returns also FALSE
Patrick Roocks
  • 3,129
  • 3
  • 14
  • 28
  • 1
    I was still getting a `FALSE` return until I used `identical(a,as.Date(character(0))` because the value showed as `character(0)` even after I had cast the result as a date earlier in my code. – Climbs_lika_Spyder Mar 20 '17 at 19:53
  • 1
    If you cast a value to Date, then it's not identical to `character(0)`, so this behavior is perfectly fine. `quote(character(0))` is also displayed as `character(0)` in the console and definitively not identical to `character(0)`. – Patrick Roocks Mar 21 '17 at 09:46
  • 1
    I was not complaining. I was just sharing in case others have a similar case. – Climbs_lika_Spyder Mar 23 '17 at 13:42
  • out of curiosity, why does `a == character(0)` return `logical(0)` instead of returning `TRUE` – stevec Aug 01 '19 at 00:50
  • Because `==` works vectorwise (cf. `c("a","b")==c("a","c")` returning `c(TRUE,FALSE)`) and `character(0)` is a "vector of type 'character' of length 0" (cf. `c("a", character(0))` is identical to `"a"`). Hence a "vector of type 'logical' of length 0" is a sound result. – Patrick Roocks Aug 06 '19 at 11:33
28

Adding the obligatory tidyverse answer. The rlang package has the function is_empty(), which does exactly what you want.

Test <- character(0)
rlang::is_empty(Test)
#[1] TRUE

This also works for empty vectors that aren't characters. For example, it works in the case that Patrick Roocks describes in comments.

Test <- as.Date(character(0))
rlang::is_empty(Test)
#[1] TRUE

Loading the 'tidyverse' package also loads is_empty().

Andrew Brēza
  • 7,705
  • 3
  • 34
  • 40
9

Use the length() method:

> check <- function(value) {
+ if (length(value)==0) {
+ print('Empty')
+ } else {
+ print('Not Empty')
+ }
+ }
> check("Hello World")
[1] "Not Empty"
> check("")
[1] "Not Empty"
> check(character(0))
[1] "Empty"
georgeawg
  • 48,608
  • 13
  • 72
  • 95
amagard
  • 339
  • 3
  • 8
9

Many people forget that functions like str_locate_all() require %>% unlist() or %>% .[[1]].

Then you can easily detect character(0) with the length() function if > 0 one can safely use the output of str_locate_all() for example.

Example:

value <- str_extract_all("kvk :", ascii_digit(8,8)) %>% unlist()
if (length(value) > 0) {
  # Do something
}
Eric Leung
  • 2,354
  • 12
  • 25
2

instead of length(), worked for me nrows()

1

My method to solve this problem is dealing with that column only by cast it into a character again and find "character(0)" instead.

For example:

df$interest_column <- as.character(df$interest_column) # Cast it into a character again
df[df$interest_column == "character(0)","interest_column"] <- NA  # Assign new value

I hope this is a solution you have asked for.

1

I was doing some micro-optimization today for a related problem: checking if a numeric vector is empty (e.g. equivalent to numeric(0)) when it can either be empty or have a value (it is never NA or NULL). In my problem the check occurs hundreds of millions of time, so it seemed reasonable to benchmark the right approach. Length benchmarks quite a bit better than other options:

vec = numeric(0)

bench::mark(
  x = { !length(vec) },
  y = { rlang::is_empty(vec) },
  z = { identical(vec, numeric(0)) },
  check = FALSE,
  min_time = 5,
  min_iterations = 100000,
  max_iterations = 100000
)
# A tibble: 3 x 6
  expression      min   median `itr/sec` `gc/sec`  n_gc
  <bch:expr> <bch:tm> <bch:tm>     <dbl>    <dbl> <dbl>
1 x             200ns    300ns  3621037.     0        0
2 y             5.2us    5.8us   166594.     8.33     5
3 z             1.3us    1.5us   618090.    12.4      2

Length checking beating identical checking by 6x and by is_empty by 4x over that. The results for the case where the vector is non-empty are similar, so irrespective of the distribution of your data, just use length.

I am cognizant that there are probably edge cases where the behaviours of these three functions aren't identical, but if like me it's just a matter of a value being either c(some, number) or numeric(0) and you want to quickly check which, use length.

aaron
  • 315
  • 1
  • 7