Patrick Parts
Patrick Parts

Reputation: 203

ifelse function on a vector

I am using the ifelse function in order to obtain either a vector with NA if all the "value" of this vector are NA or a vector with all the values not equal to "NA_NA". In my example, I would like to obtain this results

 [1] "14_mter" "78_ONHY" 

but I am obtaining this

[1] "14_mter"

my example:

vect=c("NA_NA", "14_mter", "78_ONHY")
out=ifelse(all(is.na(vec)), vec, vec[which(vec!="NA_NA")])

What is wrong in this function ?

Upvotes: 0

Views: 1478

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269461

The ifelse help file, referring to its three arguments test, yes and no, says:

ifelse returns a value with the same shape as test which is filled with elements selected from either yes or no depending on whether the element of test is TRUE or FALSE.

so if the test has a length of 1, which is the case for the code in the question, then the result will also have length 1. Instead try one of these.

1) Use if instead of ifelse. if returns the value of the chosen leg so just assign that to out.

out <- if (all(is.na(vect))) vect else vect[which(vect != "NA_NA")]

2) The collapse package has an allNA function so a variation on (1) is:

library(collapse)
out <- if (allNA(vect)) vect else vect[which(vect != "NA_NA")]

3) Although not recommended if you really wanted to use ifelse it could be done by wrapping each leg in list(...) so that the condition and two legs all have the same length, i.e. 1.

out <- ifelse(all(is.na(vect)), list(vect), list(vect[which(vect != "NA_NA")])) |> 
  unlist()

Upvotes: 1

Chris Ruehlemann
Chris Ruehlemann

Reputation: 21400

If the NAvalue is always the string NA_NA, this works:

grep("NA_NA", vect, value = TRUE, invert = TRUE)
[1] "14_mter" "78_ONHY"

While the pattern matches the NA_NA value, the invert = TRUE argument negates the match(es) and produces the unmatched values

Data:

vect=c("NA_NA", "14_mter", "78_ONHY")

Upvotes: 0

mnist
mnist

Reputation: 6956

ifelse is vectorized and its result is as long as the test argument. all(is.na(vect)) is always just length one, hence the result. a regular if/else clause is fine here.

vect <- c("NA_NA", "14_mter", "78_ONHY")

if (all(is.na(vect))) {
  out <- vect 
} else {
  out <- vect[vect != "NA_NA"]
}
out
#> [1] "14_mter" "78_ONHY"

additional note: no need for the which() here

Upvotes: 3

Related Questions