Reputation: 469
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
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
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