【问题标题】:`dplyr::case_when` Evaluation error: object 'x' not found`dplyr::case_when` 评估错误:找不到对象“x”
【发布时间】:2018-03-14 02:45:30
【问题描述】:

有谁知道为什么dplyr::case_when() 会在以下代码中产生错误?

tibble(tmp1 = sample(c(T, F), size = 32, replace = T),
       tmp2 = sample(c(T, F), size = 32, replace = T),
       tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
  mutate(tmp = apply(cbind(tmp1, tmp2, tmp3), 1, function(x) {
    case_when(
      all(x == F) ~ "N",
      any(x == T) ~ "Y"
    )
  }))

Error in mutate_impl(.data, dots) : 
  Evaluation error: object 'x' not found.

我在 Ubuntu 16.04 上使用 R 3.4.3 和 dplyr 0.7.4。

错误信息相当混乱,因为下面的代码工作正常,这表明x 没有丢失:

tibble(tmp1 = sample(c(T, F), size = 32, replace = T),
       tmp2 = sample(c(T, F), size = 32, replace = T),
       tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
  mutate(tmp = apply(cbind(tmp1, tmp2, tmp3), 1, function(x) {
    if (all(x == F)) {
      "N"
    } else if(any(x == T)) {
      "Y"
    }
  }))

仅供参考,以下代码也可以正常工作:

cbind(tmp1 = sample(c(T, F), size = 32, replace = T),
      tmp2 = sample(c(T, F), size = 32, replace = T),
      tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
  apply(1, function(x) {
    case_when(
      all(x == F) ~ "N",
      any(x == T) ~ "Y"
    )
  })

【问题讨论】:

  • @Maurits Evers 和 @www 提供了一些非常好的替代方案。但实际用例比示例更复杂(更多变量、更多规则、处理 NA 值),因此首选更灵活的形式(例如 if-else 或 case_when)。你知道为什么case_when()(比if-else更方便)代码会产生错误吗?
  • @www 没有告诉你为什么case_when 不起作用? (“问题是 case_when 不执行逐行操作。”)顺便说一句,我没有收到错误,但所有条目都是 NA
  • @MauritsEvers 好吧,如果您将case_when 放入apply,则可以进行逐行操作,请参阅问题中的更新示例。我认为@www 没有提到为什么找不到“对象 x”。我使用的是 Ubuntu 16.04,你使用的是什么系统,@MauritsEvers?它是特定于平台的问题吗?
  • @NickZeng 如果 MauritsEvers 或我提供的帖子为您的示例生成了所需的输出,请考虑接受其中一个帖子作为答案。如果您的实际用例比您在此处提供的示例更复杂,请考虑使用可以实际代表您的真实数据的示例提出一个新问题。
  • 重申一下:当我运行第一个代码块时,没有错误。但是,所有tmp 条目都是NA

标签: r dplyr tidyverse


【解决方案1】:

问题是case_when 不执行逐行操作。但是,我们可以通过使用rowSums(执行逐行操作)和case_when来简化代码。

library(dplyr)

set.seed(151)

tibble(tmp1 = sample(c(T, F), size = 32, replace = T),
       tmp2 = sample(c(T, F), size = 32, replace = T),
       tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
  mutate(tmp = case_when(
      rowSums(.) == 0   ~"N",
      rowSums(.) > 0    ~"Y" 
    ))

# # A tibble: 32 x 4
#   tmp1  tmp2  tmp3  tmp  
#   <lgl> <lgl> <lgl> <chr>
#  1 TRUE  TRUE  FALSE Y    
#  2 FALSE FALSE TRUE  Y    
#  3 FALSE FALSE TRUE  Y    
#  4 FALSE FALSE TRUE  Y    
#  5 TRUE  FALSE FALSE Y    
#  6 FALSE FALSE FALSE N    
#  7 TRUE  FALSE FALSE Y    
#  8 FALSE TRUE  FALSE Y    
#  9 TRUE  TRUE  FALSE Y    
# 10 FALSE FALSE TRUE  Y    
# # ... with 22 more rows

或者因为只有两个条件,rowSumsifelse 应该没问题。

set.seed(151)

tibble(tmp1 = sample(c(T, F), size = 32, replace = T),
       tmp2 = sample(c(T, F), size = 32, replace = T),
       tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
  mutate(tmp = ifelse(rowSums(.) == 0, "N", "Y"))
# # A tibble: 32 x 4
#   tmp1  tmp2  tmp3  tmp  
#   <lgl> <lgl> <lgl> <chr>
#  1 TRUE  TRUE  FALSE Y    
#  2 FALSE FALSE TRUE  Y    
#  3 FALSE FALSE TRUE  Y    
#  4 FALSE FALSE TRUE  Y    
#  5 TRUE  FALSE FALSE Y    
#  6 FALSE FALSE FALSE N    
#  7 TRUE  FALSE FALSE Y    
#  8 FALSE TRUE  FALSE Y    
#  9 TRUE  TRUE  FALSE Y    
# 10 FALSE FALSE TRUE  Y    
# # ... with 22 more rows

【讨论】:

    【解决方案2】:

    如何使用Reduce 和逻辑或?

    set.seed(151);
    tibble(tmp1 = sample(c(T, F), size = 32, replace = T),
           tmp2 = sample(c(T, F), size = 32, replace = T),
           tmp3 = sample(c(T, F), size = 32, replace = T)) %>%
        mutate(tmp = Reduce(`|`, list(tmp1, tmp2, tmp3)))
    ## A tibble: 32 x 4
    #   tmp1  tmp2  tmp3  tmp
    #   <lgl> <lgl> <lgl> <lgl>
    # 1 TRUE  TRUE  FALSE TRUE
    # 2 FALSE FALSE TRUE  TRUE
    # 3 FALSE FALSE TRUE  TRUE
    # 4 FALSE FALSE TRUE  TRUE
    # 5 TRUE  FALSE FALSE TRUE
    # 6 FALSE FALSE FALSE FALSE
    # 7 TRUE  FALSE FALSE TRUE
    # 8 FALSE TRUE  FALSE TRUE
    # 9 TRUE  TRUE  FALSE TRUE
    #10 FALSE FALSE TRUE  TRUE
    ## ... with 22 more rows
    

    【讨论】:

      【解决方案3】:

      事实证明,这是一个错误,可能与混合评估器有关:https://github.com/tidyverse/dplyr/issues/3422

      【讨论】:

        猜你喜欢
        • 2018-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多