如何根据使用R对数据帧中前两列的求值,有条件地用NA填充行



我有一个这样的数据帧:

df <- data.frame(
Metric = c('WI', NA, 'MN', NA, 'CO', NA),
Eval = c('WI', NA, 'AK', NA, 'CO', NA),
colA = c(30, 'ABC', 45, 'DEF', 2, 'XYZ'),
colB = c(25, 'BEC', 23, 'FED', 50, 'HIJ')
)

我想评估Metric列和Eval列是否相等,如果相等,用NA填充Metric列右侧的所有内容,结果如下:

df_desired <- data.frame(
Metric = c('WI', NA, 'MN', NA, 'CO', NA),
Eval = c(NA, NA, 'AK', NA, NA, NA),
colA = c(NA, 'ABC', 45, 'DEF', NA, 'XYZ'),
colB = c(NA, 'BEC', 23, 'FED', NA, 'HIJ')
)

使用R,最好是使用tidyverse函数,最好的方法是什么?我试着使用mutate/across,但在这里定义条件让我很失望

创建一个逻辑向量,并根据行/列索引/名称进行赋值(base R更直接(

i1 <- with(df, Metric == Eval & !is.na(Metric) & !is.na(Eval))
df[i1, -1] <- NA

-输出

> df
Metric Eval colA colB
1     WI <NA> <NA> <NA>
2   <NA> <NA>  ABC  BEC
3     MN   AK   45   23
4   <NA> <NA>  DEF  FED
5     CO <NA> <NA> <NA>
6   <NA> <NA>  XYZ  HIJ

或者使用dplyr,创建一列逻辑向量('i1'(,将across列的'Eval'循环为'colB',使用case_when/ifelse/if_else/replace根据'i1'将值更改为NA,并通过分配给NULL来移除临时列

library(dplyr)
df %>% 
mutate(i1 = Metric == Eval, 
across(Eval:colB, ~ case_when(i1 ~ NA_character_, TRUE ~ .)), 
i1 = NULL)

-输出

Metric Eval colA colB
1     WI <NA> <NA> <NA>
2   <NA> <NA>  ABC  BEC
3     MN   AK   45   23
4   <NA> <NA>  DEF  FED
5     CO <NA> <NA> <NA>
6   <NA> <NA>  XYZ  HIJ

使用mutate()if_else()有条件地替换值:

df |>
mutate(colA = if_else(Metric == Eval, NA_character_, colA, missing = colA))
#>   Metric Eval colA colB
#> 1     WI   WI <NA>   25
#> 2   <NA> <NA>  ABC  BEC
#> 3     MN   AK   45   23
#> 4   <NA> <NA>  DEF  FED
#> 5     CO   CO <NA>   50
#> 6   <NA> <NA>  XYZ  HIJ

注意,我们不能只使用NA,我们必须将它与现有的列类型相匹配。在您的示例中,colAcolB是字符向量,因此它是NA_character_。我们必须指定missing来处理NA == NA的情况。

要在多个列中推广这一点,请使用across()并将if_else()包装在一个匿名函数中:

df |>
mutate(across(Eval:colB, ~if_else(Metric == Eval, NA_character_, ., missing = .)))
#>   Metric Eval colA colB
#> 1     WI <NA> <NA> <NA>
#> 2   <NA> <NA>  ABC  BEC
#> 3     MN   AK   45   23
#> 4   <NA> <NA>  DEF  FED
#> 5     CO <NA> <NA> <NA>
#> 6   <NA> <NA>  XYZ  HIJ

最新更新