在mutate中使用ifelse并处理NA

时间:2018-09-27 22:05:23

标签: r if-statement dplyr

感谢您的时间。

我对在ifelse函数中使用mutate有疑问。 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

我正在ifelse中使用嵌套的mutate语句来创建名为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"))))

(道歉的格式-我试图尽我所能对这种格式进行堆栈溢出。)

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

  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

我已经找到了很多答案,却找不到任何答案。我可以创建一个解决方法,然后返回并手动将条目分配给Yellow,但是从编程的角度来看,我不喜欢该选项。

此外,我只是对为什么会发生这种情况感到好奇。我已经遇到了几次这个问题。


感谢您的时间!

2 个答案:

答案 0 :(得分:3)

您应在此处使用case_when,但之所以得到NA是因为第二个ifelse。关于NA如何在R中传播的一件有趣的事情是(来自文档)“如果结果不明确,结果将是NA”。因此,因为我们知道无论FALSE为何它都是NA,所以我们有

NA & FALSE
#> [1] FALSE

但是由于模棱两可,NA在此处传播。

NA & TRUE
#> [1] NA

第5行的TRUEYellow,但是str_detect将返回NA,因此ifelse返回NA。您可以通过在该行中添加& !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

答案 1 :(得分:1)

试试看。 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