Woj
Woj

Reputation: 469

How do I remove elements in 3 vectors if one vector is missing?

Let's say I have the following code:

x <- c(NA ,1,NA,2,3,4)
y <- c(7,4,2,7,4,6)
z <- c(3,9,6,3,4,5)

for (i in 1:length(x)){
  if (is.na(x[i])){
    cat("No value\n")
    x <- x[!is.na(x)]
    y <- y[!y]
    z <- z[!z]
}

For every element in X that is missing (or for Y and Z too, I suppose), I would like to remove that element from the x vector and remove the element from the corresponding index for y in z (i.e. Since the first element in x is missing, I want to remove that element, AND 7 and 3 from y and z respectively.) The for loop shows my attempt at this, however, I have not got the desired output:

X array: 
1 
 2 
 3 
 4 

 Y array: 
 

 Z array: 
 

Here is the desired output, or how I would like the vectors to end up.

 X array: 
 1 
 2 
 3 
 4 

 Y array: 
 4 
 7 
 4 
 6 

 Z array: 
 9 
 3 
 4 
 5 

Upvotes: 1

Views: 51

Answers (2)

akrun
akrun

Reputation: 887231

We can create a single index and use that to subset. Place the vectors in a a list and apply is.na to check for NA elements, Reduce to a single logical vector with |, negate (!) and use that for subsetting the vectors

i1 <- !Reduce(`|`, lapply(list(x, y, z), is.na))
x[i1]
#[1] 1 2 3 4
y[i1]
#[1] 4 7 4 6
 z[i1]
#[1] 9 3 4 5

Or using filter after converting to a data.frame or tibble

library(dplyr) # 1.0.0
tibble(x, y, z) %>%
       filter(across(everything(), ~ !is.na(.)))
# A tibble: 4 x 3
#      x     y     z
#  <dbl> <dbl> <dbl>
#1     1     4     9
#2     2     7     3
#3     3     4     4
#4     4     6     5

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76460

Here is a base R way.

Create a temporary matrix with cbind, then see by row if the number of non-NA elements is equal to 3, the number of columns. Use this logical vecto to subset x, y, z.

i <- rowSums(!is.na(cbind(x,y,z))) == 3
x[i]
#[1] 1 2 3 4
y[i]
#[1] 4 7 4 6
z[i]
#[1] 9 3 4 5

Another base R way.

apply by row function anyNA to the same temp matrix. Negate the result and use it to subset the input vectors.

j <- !apply(cbind(x,y,z), 1, anyNA)
x[j]
#[1] 1 2 3 4
y[j]
#[1] 4 7 4 6
z[j]
#[1] 9 3 4 5

Upvotes: 2

Related Questions