Reputation: 11
I have a function that sometimes returns a value of NULL and sometimes returns a data frame with 0 rows. I would like do something else. Say that object x
is an object that can be NULL
or 0 rows
x1 <- some operation on x
if(is.null(x) & is.null(x1) { do stuff }
I'm trying to think of a way to query a data frame that will return NULL
if it has 0 rows and will return something that is not NULL
if it has any rows. That is because the following does not work:
while(is.null(x) | dim(x)[1] == 0) { do stuff }
because when x is null you get a argument is of length zero error when you query dim(x)
Every thing I can think of returns <NA>
and not NULL
. Actually I think my code would look like
while(is.null(x) & is.null(some.operation(x)) { do stuff }
Upvotes: 1
Views: 465
Reputation: 11
I came up with a solution of:
makeNull<-function(x){
if(is.null(x)) {return(x)}
if(dim(x)[1]==0) {x<-NULL}
x
}
so then I would enter
while(is.null(x)&is.null(makeNull(x)){do stuff}
to replace
while(is.null(x)|dim(x)[1]){do stuff}
Upvotes: 0
Reputation: 38500
This function will return NULL if the data.frame has 0 rows or the number of rows if the data.frame is has at least one row.
myFunc <- function(x) return(list(NULL, nrow(x))[[(!(is.null(nrow(x) > 0))) + 1L]])
I use list
to encapsulate NULL as an element that can be returned. The second element of the list is the number of rows Then, the proper list element is returned with [[
.
Here are a couple of test examples
# NULL input
myFunc(NULL)
NULL
# empty data.frame
myFunc(data.frame())
NULL
# data.frame with single element
myFunc(data.frame(a=1))
# data.frame with vector of length 10
[1] 1
myFunc(data.frame(a=1:10))
[1] 10
Upvotes: 0
Reputation: 60462
If I understand your question correctly, then you just need to change
while(is.null(x)|dim(x)[1]==0){do stuff}
to
while(is.null(x) || dim(x)[1]==0){do stuff}
The logical OR (|
) operator is vectorised. This both sides are always evaluated, e.g. we always evaluate is.null(x)
and dim(x)
.
In contrast, the operator ||
works for scalers (actually it also works on vectors, but only uses the first value). This means that we only evaluate dim(x)
if is.null(x)
returns FALSE
.
For example
# Vectorised, so stop is called
TRUE | stop("Now!")
#Error: Now!
with
# Scaler: stop is not evaluated.
TRUE || stop("Now!")
#[1] TRUE
Upvotes: 3