Let's say we have a statement that produces integer(0)
, e.g.
a <- which(1:3 == 5)
What is the safest way of catching this?
any
. It will return FALSE for either which(1:3==5)
or for 1:3==5
.
integer(0)
, which I produced using which
as an example.
which
? This would be very helpful for me to avoid bad code.
That is R's way of printing a zero length vector (an integer one), so you could test for a
being of length 0:
R> length(a)
[1] 0
It might be worth rethinking the strategy you are using to identify which elements you want, but without further specific details it is difficult to suggest an alternative strategy.
If it's specifically zero length integers, then you want something like
is.integer0 <- function(x)
{
is.integer(x) && length(x) == 0L
}
Check it with:
is.integer0(integer(0)) #TRUE
is.integer0(0L) #FALSE
is.integer0(numeric(0)) #FALSE
You can also use assertive
for this.
library(assertive)
x <- integer(0)
assert_is_integer(x)
assert_is_empty(x)
x <- 0L
assert_is_integer(x)
assert_is_empty(x)
## Error: is_empty : x has length 1, not 0.
x <- numeric(0)
assert_is_integer(x)
assert_is_empty(x)
## Error: is_integer : x is not of class 'integer'; it has class 'numeric'.
!length(x)
rather than length(x)==0
length(x) == 0L
reads more clearly to me.
L
suffix to a number makes R store it as an integer rather than a floating point value. See, e.g., cran.r-project.org/doc/manuals/R-lang.html#Constants
Maybe off-topic, but R features two nice, fast and empty-aware functions for reducing logical vectors -- any
and all
:
if(any(x=='dolphin')) stop("Told you, no mammals!")
is.empty
, cuz some functions return integer(0)
instead of NA
or NULL
. But for now your way is the most straightforward, and works vector-wise which is a big advantage over length(a)
.
Inspired by Andrie's answer, you could use identical
and avoid any attribute problems by using the fact that it is the empty set of that class of object and combine it with an element of that class:
attr(a, "foo") <- "bar"
identical(1L, c(a, 1L))
#> [1] TRUE
Or more generally:
is.empty <- function(x, mode = NULL){
if (is.null(mode)) mode <- class(x)
identical(vector(mode, 1), c(x, vector(class(x), 1)))
}
b <- numeric(0)
is.empty(a)
#> [1] TRUE
is.empty(a,"numeric")
#> [1] FALSE
is.empty(b)
#> [1] TRUE
is.empty(b,"integer")
#> [1] FALSE
if ( length(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'")
#[1] "nothing returned for 'a'"
On second thought I think any is more beautiful than length(.)
:
if ( any(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'")
if ( any(a <- 1:3 == 5 ) ) print(a) else print("nothing returned for 'a'")
You can easily catch integer(0) with function identical(x,y)
x = integer(0)
identical(x, integer(0))
[1] TRUE
foo = function(x){identical(x, integer(0))}
foo(x)
[1] TRUE
foo(0)
[1] FALSE
another option is rlang::is_empty
(useful if you're working in the tidyverse)
The rlang namespace does not seem to be attached when attaching the tidyverse via library(tidyverse)
- in this case you use purrr::is_empty
, which is just imported from the rlang
package.
By the way, rlang::is_empty
uses user Gavin's approach.
rlang::is_empty(which(1:3 == 5))
#> [1] TRUE
isEmpty()
is included in the S4Vectors base package. No need to load any other packages.
a <- which(1:3 == 5)
isEmpty(a)
# [1] TRUE
Success story sharing
length(NULL) == 0
is alsoTRUE
. user E Nord's answer would be an option to test forinteger(0)
only