Mute, por linha, com base em strings correspondentes ou NA em um subconjunto de colunas
Algum conselho sobre como combinar strings, dentro de uma linha, em várias colunas?
Adaptado de Remover linhas onde todas as variáveis são NA usando dplyr onde elas estão correspondendo apenas a NAs nas colunas e filtrando-as - não criando uma nova variável.
Exemplo de brinquedo:
library(dplyr)
df <- tibble(a = c('a', 'a', 'a', NA),
b1 = c('b', 'c', NA, NA),
b2 = c('d', NA, NA, NA),
b3 = c('e', NA, NA, NA),
b4 = c('f', NA, NA, NA))
df
# A tibble: 4 x 5
a b1 b2 b3 b4
<chr> <chr> <chr> <chr> <chr>
1 a b d e f
2 a c NA NA NA
3 a NA NA NA NA
4 NA NA NA NA NA
Para criar uma nova variável all_na
se toda a linha for NA:
df %>%
rowwise() %>%
mutate(all_na = all(is.na(across())))
# A tibble: 4 x 6
# Rowwise:
a b1 b2 b3 b4 all_na
<chr> <chr> <chr> <chr> <chr> <lgl>
1 a b d e f FALSE
2 a c NA NA NA FALSE
3 a NA NA NA NA FALSE
4 NA NA NA NA NA TRUE
Para criar uma nova variável se apenas um subconjunto das colunas (começando com 'b') for NAb_is_na
df %>%
rowwise() %>%
mutate(b_is_na = all(is.na(across(starts_with('b'))))) %>%
ungroup()
# A tibble: 4 x 6
a b1 b2 b3 b4 b_is_na
<chr> <chr> <chr> <chr> <chr> <lgl>
1 a b d e f FALSE
2 a c NA NA NA FALSE
3 a NA NA NA NA TRUE
4 NA NA NA NA NA TRUE
Pergunta:
No entanto, não tenho certeza de como criar uma variável se dentro de uma linha, para um subconjunto de colunas for uma correspondência de string OR NA
, por exemplo,'c' or NA
Saída desejada:
# A tibble: 4 x 6
a b1 b2 b3 b4 b_is_na
<chr> <chr> <chr> <chr> <chr> <lgl>
1 a b d e f FALSE
2 a c NA NA NA TRUE
3 a NA NA NA NA TRUE
4 NA NA NA NA NA TRUE
Respostas
Uma base R
opção e uma opção vetorizada eficiente estariam rowSums
em uma lógicamatrix
nm1 <- startsWith(names(df), 'b')
df$b_is_na <- rowSums(df[nm1] == 'c'|is.na(df[nm1])) > 0
df$b_is_na
#[1] FALSE TRUE TRUE TRUE
Também pode ser usado com omutate
library(dplyr)
df %>%
mutate(b_is_na = rowSums(select(., starts_with('b')) ==
'c'|is.na(select(., starts_with('b')))) > 0)
# A tibble: 4 x 6
# a b1 b2 b3 b4 b_is_na
# <chr> <chr> <chr> <chr> <chr> <lgl>
#1 a b d e f FALSE
#2 a c <NA> <NA> <NA> TRUE
#3 a <NA> <NA> <NA> <NA> TRUE
#4 <NA> <NA> <NA> <NA> <NA> TRUE
NOTA: Usar rowwise
seria uma maneira ineficiente
Ou com c_across
, mas pode não ser tão ideal
df %>%
rowwise %>%
mutate(b_is_na = {
tmp <- c_across(starts_with('b'))
any(is.na(tmp)|tmp == 'c') }) %>%
ungroup
# A tibble: 4 x 6
# a b1 b2 b3 b4 b_is_na
# <chr> <chr> <chr> <chr> <chr> <lgl>
#1 a b d e f FALSE
#2 a c <NA> <NA> <NA> TRUE
#3 a <NA> <NA> <NA> <NA> TRUE
#4 <NA> <NA> <NA> <NA> <NA> TRUE