【问题标题】:How to conditionally fill in rows with NAs depending on an evaluation of the first two columns in a dataframe using R?如何根据使用 R 对数据框中前两列的评估有条件地用 NA 填充行?
【发布时间】:2021-11-08 17:21:24
【问题描述】:

我有一个这样的数据框:

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,但在这里定义条件让我失望。

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    创建一个逻辑向量,根据行/列索引/名称进行赋值(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将值更改为NA,基于'i1' 并通过分配给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
    

    【讨论】:

      【解决方案2】:

      使用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
      

      【讨论】:

        猜你喜欢
        • 2021-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-25
        • 2018-03-02
        • 2013-02-12
        • 2018-07-28
        • 1970-01-01
        相关资源
        最近更新 更多