Count NAs rowwise from multiple variables provided as vector

Viewed 94

I have a data:

test_df <- data.frame(x1 = c("a", "b", "c", NA, NA), 
                      x2 = sample(1:5),
                      x3 = c(T, NA, F, T, NA),
                      x4 = c(NA, NA, 1, 2, 3),
                      stringsAsFactors = F)

colset1 <- c("x1", "x2", "x3")
colset2 <- c("x2", "x3", "x4")

data frame and vectors containing variable names.

How to check (best in dplyr way), if any row of columns provided in a vector (colset) contains any NAs?

Expected answer for colset1 is TRUE FALSE TRUE FALSE FALSE, and for colset2 is FALSE FALSE TRUE TRUE FALSE (best if can be mutated as a new logical variable, doesn't matter).

The alternative question will be: how to count NAs in that columns? Expected answer for colset1 is 0 1 0 1 2, and for colset2 is 1 2 0 0 1

I was trying with mutating ...ifelse(length(sum(is.na(vars(colset1)))) == 0) but something was still missing, it didn't work and I got lost in own code :)

Thanks!

3 Answers

One dplyr solution could be:

test_df %>%
 mutate(colset1 = Reduce(`|`, across(colset1, ~ is.na(.))),
        colset2 = Reduce(`|`, across(colset2, ~ is.na(.))))

To get the counts:

test_df %>%
 mutate(colset1 = rowSums(across(colset1, ~ is.na(.))),
        colset2 = rowSums(across(colset2, ~ is.na(.))))

    x1 x2    x3 x4 colset1 colset2
1    a  3  TRUE NA       0       1
2    b  4    NA NA       1       2
3    c  1 FALSE  1       0       0
4 <NA>  5  TRUE  2       1       0
5 <NA>  2    NA  3       2       1

No need for dplyr. You can simply use rowSums, i.e.

!rowSums(is.na(test_df[colset1])) > 0
#[1]  TRUE FALSE  TRUE FALSE FALSE

!rowSums(is.na(test_df[colset2])) > 0
#[1] FALSE FALSE  TRUE  TRUE FALSE

To get the actual number of NAs, you can remove the logical > 0 and the negate symbol (!), i.e.

rowSums(is.na(test_df[colset1]))
#[1] 0 1 0 1 2
rowSums(is.na(test_df[colset2]))
#[1] 1 2 0 0 1
test_df
    x1 x2    x3 x4
1    a  4  TRUE NA
2    b  3    NA NA
3    c  2 FALSE  1
4   NA  5  TRUE  2
5   NA  1    NA  3
is_na(test_df)
        x1    x2    x3    x4
[1,] FALSE FALSE FALSE  TRUE
[2,] FALSE FALSE  TRUE  TRUE
[3,] FALSE FALSE FALSE FALSE
[4,]  TRUE FALSE FALSE FALSE
[5,]  TRUE FALSE  TRUE FALSE

Use na.tools package

Related