问题描述
任何建议如何在一行中跨多列匹配字符串?
改编自 Remove rows where all variables are NA using dplyr,其中它们仅匹配各列之间的NA,并对其进行过滤-不创建新变量。
玩具示例:
library(dplyr)
df <- tibble(a = c('a','a',NA),b1 = c('b','c',NA,b2 = c('d',b3 = c('e',b4 = c('f',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
要创建一个新变量all_na
(如果整行都是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
如果仅列的子集(以'b'开头)为NA b_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
问题:
但是,我不确定如何在行内创建变量,因为列的子集是字符串匹配或NA
,例如'c' or NA
所需的输出:
# 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
解决方法
在逻辑base R
上,rowSums
选项和有效的矢量化选项为matrix
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
它也可以与mutate
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
注意:使用rowwise
效率不高
或与c_across
一起使用,但这可能不是最佳选择
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