R:case_when,当使用dplyr mutate产生意外的“ NA”时

时间:2019-03-01 15:04:56

标签: r dplyr na mutate

我具有以下用户定义的功能

vareas1 <- function(a, b, c) {
  case_when(a == 1 ~ "top",
            b == 1 ~ "left",
            c == 1 ~ "right",
            near(a, 1/3) && near(b, 1/3) && near(c, 1/3) ~ "centre"
  )
}

test2 <- vareas1(1/3, 1/3, 1/3)

正确评估为

[1] "centre

但是,当通过dplyr的mutate应用它时,有时会产生NA。示例如下:

test1 <- data.frame("a" = c(1, 0, 0, 1/3),
                "b" = c(0, 1, 0, 1/3), 
                "c" = c(0, 0, 1, 1/3)) %>% mutate(area1 = vareas1(a, b, c))

结果是:

          a         b         c area1
1 1.0000000 0.0000000 0.0000000   top
2 0.0000000 1.0000000 0.0000000  left
3 0.0000000 0.0000000 1.0000000 right
4 0.3333333 0.3333333 0.3333333  <NA>

第[4]行中的NA而不是结果“中心”是意外的,我不知道它的来源。

我认为可能是由于a,b和c列的类别,所以我修改了功能

  vareas1_int <- function(a, b, c) {
            case_when(a == as.integer(1 * 10e6) ~ "top",
                      b == as.integer(1 * 10e6) ~ "left",
                      c == as.integer(1 * 10e6) ~ "right",
                      near(a, as.integer(1/3 * 10e+6) && 
                      near(b, as.integer(1/3 * 10e+6)) && 
                      near(c, as.integer(1/3 * 10e+6))) ~ "centre"
  )
}

并将a,b,c更改为合适的整数:

test1 <- test1 %>%
mutate(a_mil = as.integer(a * 10e+6),
     b_mil = as.integer(b * 10e+6),
     c_mil = as.integer(c * 10e+6))

但是结果是一样的:

      a         b         c area1    a_mil    b_mil    c_mil area_int
1 1.0000000 0.0000000 0.0000000   top 10000000        0        0      top
2 0.0000000 1.0000000 0.0000000  left        0 10000000        0     left
3 0.0000000 0.0000000 1.0000000 right        0        0 10000000    right
4 0.3333333 0.3333333 0.3333333  <NA>  3333333  3333333  3333333     <NA>

谢谢您的帮助!

(这个类似的post不能解决我的问题。)

1 个答案:

答案 0 :(得分:5)

您需要&而不是&&才能使函数与矢量一起使用。

library(tidyverse)

vareas1 <- function(a, b, c) {
  case_when(a == 1 ~ "top",
    b == 1 ~ "left",
    c == 1 ~ "right",
    near(a, 1/3) & near(b, 1/3) & near(c, 1/3) ~ "centre"
  )
}

data.frame("a" = c(1, 0, 0, 1/3),
  "b" = c(0, 1, 0, 1/3), 
  "c" = c(0, 0, 1, 1/3)) %>% mutate(area1 = vareas1(a, b, c))