27

I am trying to return null using ifelse in R. But it throws an error message. Any suggestion please.

Here is my code:

cntr1 <- ifelse(unlist(gregexpr("---",path_info[j], fixed = TRUE, useBytes = TRUE)) > 0, 3 * length(unlist(gregexpr("---",path_info[j], fixed = TRUE, useBytes = TRUE))),NULL )

Error message is:

Error in ifelse(unlist(gregexpr("---", path_info[j], fixed = TRUE, useBytes = TRUE)) >  : 
  replacement has length zero In addition: Warning message:
In rep(no, length.out = length(ans)) :
  'x' is NULL so the result will be NULL
Sotos
  • 51,121
  • 6
  • 32
  • 66
user2293224
  • 2,128
  • 5
  • 28
  • 52
  • I don't believe that's possible. From the help page of `ifelse`, section `Value`: `A vector of the same length [...] as test and data values from the values of yes or no`. And `length(NULL)` returns zero so your `no` can't even be recycled. – Rui Barradas Aug 22 '17 at 10:29
  • I don't know if it will really be useful to you but maybe try instead of returning `NULL` to return `"NULL"` so that your ifelse works and then do a `eval(parse(text = ...) )` to really get the `NULL` to appear ? – MBB Aug 22 '17 at 10:43
  • 4
    Why would you need it to return `NULL` anyway? You cannot have `NULL`s in atomic vectors anyway. `NA` is the right object for missing values in R. – LyzandeR Aug 22 '17 at 10:52
  • @LyzandeR use of NA does not give length 0. – user2293224 Aug 23 '17 at 02:45

4 Answers4

22

I came up with three different approaches to return NULL in an ifelse-like scenario.

In this scenario b should be NULL when a is NULL

a <- NULL
is.null(a)  #TRUE

b <- switch(is.null(a)+1,"notNullHihi",NULL)
b <- if(is.null(a)) NULL else {"notNullHihi"}
b <- unlist(ifelse(is.null(a),list(NULL),"notNullHihi"))

is.null(b)  #TRUE for each of them
Andre Elrico
  • 10,956
  • 6
  • 50
  • 69
  • The `unlist` approach can be more annoying as it can modify an object in the `FALSE` case (e.g. if you want to return a `data.frame`) – ztl Nov 07 '19 at 09:41
  • That's a good illustration why programming in R is painful. These small annoying things that one stumbles over again and again. And most of the time, the error message won't really tell you why you F failed, and you have to go inside it, execute code line by line and see what eventually falls. – Jonh Smith Nov 21 '22 at 03:16
4

I needed a similar functionality in one of my recent applications. This is how I came up with a solution.

obj <- "val1"

# Override a with null (this fails)
newobj <- ifelse(a == "val1", NULL, a)

# Separating the ifelse statement to if and else works

if(obj == "val1") newobj <- NULL else newobj <- obj

Atakan
  • 416
  • 3
  • 14
1

In your specific case, where yes and no of ifelse are single-element vectors, you can try to return the results as lists

ifelse(c(TRUE,FALSE,TRUE),list(1),list(NULL))
#[[1]]
#[1] 1
#
#[[2]]
#NULL
#
#[[3]]
#[1] 1

This approach would also work if either of yes or no are multi-element lists. See for instance

x=as.list(1:3)
y=c(as.list(letters[1:2]),list(NULL))
ifelse(x<2,x,y)
#[[1]]
#[1] 1
#
#[[2]]
#[1] "b"
#
#[[3]]
#NULL
cryo111
  • 4,444
  • 1
  • 15
  • 37
1

use switch() rather than ifelse() if you want to return NULL

reference:
https://www.r-bloggers.com/2017/02/use-switch-instead-of-ifelse-to-return-a-null/

Kevin Chen
  • 51
  • 2