【问题标题】:Using ifelse within mutate and handling NA's在 mutate 中使用 ifelse 并处理 NA
【发布时间】:2019-03-03 21:16:03
【问题描述】:

感谢您的宝贵时间。

我有一个关于在 mutate 函数中使用 ifelse 的问题。 ifelse 来自base R,而mutate 来自dplyr 包。

我的问题是关于 ifelse 如何处理 NA 值。

我有两个字符向量: example_character_vector 包含一些单词和偶尔的 NA 值,而另一个向量 color_indicator 仅包含单词 Green、Yellow 和 Red。

我想改变我的数据框example_data_frame 以创建一个新的override_color_indicator 变量,该变量根据example_character_vector 中的条件将一些黄色转换为绿色。

示例数据:

example_character_vector <- c("Basic", NA, "Full", "None", NA, "None", 
NA)
color_indicator <- c("Green", "Green", "Yellow", "Yellow", "Yellow", 
"Red", "Red")

example_data_frame <- data.frame(example_character_vector,
                                color_indicator)

这个 example_data_frame 看起来像这样:

  example_character_vector color_indicator
1                    Basic           Green
2                     <NA>           Green
3                     Full          Yellow
4                     None          Yellow
5                     <NA>          Yellow
6                     None             Red
7                     <NA>             Red

我在mutate 中使用嵌套的ifelse 语句来创建一个名为override_color_indicator 的新列。

如果color_indicator 是黄色并且example_character_vector 包含单词“Full”,我希望override_color_indicator 是绿色(这是我数据中的一个特殊情况)。否则,我希望override_color_indicatorcolor_indicator 完全相同。

这是我的变异:

example_data_frame <- example_data_frame %>% 
  mutate(override_color_indicator = 
          ifelse(color_indicator == "Green",
                 "Green",
            ifelse(color_indicator == "Yellow" & 
                          str_detect(example_character_vector, "Full"),
                   "Green",
                      ifelse(color_indicator == "Yellow" & 
                        !str_detect(example_character_vector, "Full") |
                             color_indicator == "Yellow" & 
                        is.na(character_vector),
                             "Yellow",
                             "Red"))))

(为格式化道歉 - 我试图为 Stack Overflow 尽可能地格式化它。)

上面的代码产生了这个数据框:

  example_character_vector color_indicator override_color_indicator
1                    Basic           Green                    Green
2                     <NA>           Green                    Green
3                     Full          Yellow                    Green
4                     None          Yellow                   Yellow
5                     <NA>          Yellow                     <NA>
6                     None             Red                      Red
7                     <NA>             Red                      Red

我的问题是,在第 5 行,override_color_indicator 颜色中引入了 NA。我希望它不是 NA,而是“黄色”。

为了清楚起见,这是我想要的数据框:

  example_character_vector color_indicator override_color_indicator
1                    Basic           Green                    Green
2                     <NA>           Green                    Green
3                     Full          Yellow                    Green
4                     None          Yellow                   Yellow
5                     <NA>          Yellow                   Yellow
6                     None             Red                      Red
7                     <NA>             Red                      Red

我已经寻找了很多答案,但在任何地方都找不到。我可以创建一个解决方法并返回并手动将条目分配给黄色,但从编程的角度来看,我不喜欢这个选项。

另外,我只是有点好奇为什么会发生这种行为。我已经遇到过几次这个问题了。


感谢您的宝贵时间!

【问题讨论】:

    标签: r if-statement dplyr


    【解决方案1】:

    你应该在这里使用case_when,但是你得到NA的原因是因为第二个ifelse。关于NA 如何在 R 中传播的一件有趣的事情是(来自文档)“如果结果不明确,结果将为 NA”。所以因为我们知道这将是FALSE,而不管NA,我们有

    NA & FALSE
    #> [1] FALSE
    

    但由于这是模棱两可的,NA 在这里传播。

    NA & TRUE
    #> [1] NA
    

    第 5 行有TRUE 对应Yellow,但str_detect 将返回NA,所以ifelse 返回NA。您可以通过在该行中添加 &amp; !is.na(example_character_vector) 来解决此问题:

    library(tidyverse)
    example_data_frame <- structure(list(example_character_vector = c("Basic", NA, "Full", "None", NA, "None", NA), color_indicator = c("Green", "Green", "Yellow", "Yellow", "Yellow", "Red", "Red")), class = "data.frame", row.names = c(NA, -7L))
    example_data_frame %>%
      mutate(
        override_color_indicator =
          ifelse(
            color_indicator == "Green",
            "Green",
            ifelse(
              color_indicator == "Yellow" &
                str_detect(example_character_vector, "Full") & !is.na(example_character_vector),
              "Green",
              ifelse(
                color_indicator == "Yellow" &
                   (!str_detect(example_character_vector, "Full") | is.na(example_character_vector)),
                "Yellow",
                "Red"
              )
            )
          )
      )
    #>   example_character_vector color_indicator override_color_indicator
    #> 1                    Basic           Green                    Green
    #> 2                     <NA>           Green                    Green
    #> 3                     Full          Yellow                    Green
    #> 4                     None          Yellow                   Yellow
    #> 5                     <NA>          Yellow                   Yellow
    #> 6                     None             Red                      Red
    #> 7                     <NA>             Red                      Red
    

    但一定要用case_when

    【讨论】:

      【解决方案2】:

      试试这个。 case_when 是一个更灵活的矢量化if 并允许您使用TRUE 说“否则,使用color_indicator 中的值。

      example_data_frame <- structure(list(example_character_vector = c("Basic", NA, "Full", "None", NA, "None", NA), color_indicator = c("Green", "Green", "Yellow", "Yellow", "Yellow", "Red", "Red")), class = "data.frame", row.names = c(NA, -7L))
      
      library(dplyr)
      example_data_frame %>%
        mutate(x = case_when(color_indicator == "Yellow" &
                              example_character_vector == "Full" ~ "Green",
                             TRUE ~ color_indicator))
      #>   example_character_vector color_indicator                        x 
      #> 1                    Basic           Green                    Green
      #> 2                     <NA>           Green                    Green
      #> 3                     Full          Yellow                    Green
      #> 4                     None          Yellow                   Yellow
      #> 5                     <NA>          Yellow                   Yellow
      #> 6                     None             Red                      Red
      #> 7                     <NA>             Red                      Red
      

      【讨论】:

      • @CalumYou 我感谢您的贡献,但我一般会建议在其他人的答案中编辑代码时稍微轻松一些。
      • 会牢记这一点。抱歉覆盖:不想重复,我已经写出了同样的东西。
      猜你喜欢
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-03
      • 2014-08-21
      相关资源
      最近更新 更多