首页 > 解决方案 > 如何编写一个使用 dplyr 来检查变量是否没有 NA 值的函数?

问题描述

我有创建任意示例数据的简单代码:

library(assertr)
library(tidyverse)
set.seed(1)
df <- tibble(id = 1:10, value = rnorm(10, 0, 1)) %>%
  mutate(value = if_else(abs(value) < 0.5, NA_real_, value))

数据如下所示:

> df
# A tibble: 10 x 2
      id   value
   <int>   <dbl>
 1     1  -0.626
 2     2  NA    
 3     3  -0.836
 4     4   1.60 
 5     5  NA    
 6     6  -0.820
 7     7  NA    
 8     8   0.738
 9     9   0.576
10    10  NA   

现在,我正在尝试编写一个函数来检查给定列(在本例中为value列)中的任何行是否具有 NA 值,如果有则抛出错误。如果他们不这样做,它应该返回未修改的原始数据,以便管道可以继续。这很简单,没有函数:

df %>% verify(sum(is.na(value)) == 0)

# Outputs "Error: assertr stopped execution"

然而,将它包装在一个函数中会导致困难。我尝试使用lazyeval

verify_not_missing <- function(.data, v) {
  .data %>% verify(sum(is.na(lazyeval::lazy(v))) == 0)
}
df %>% verify_not_missing(value)

但这不会引发任何错误或停止执行。它默默地继续执行。同样,从dplyr programming vignette,我认为以下方法可行:

verify_not_missing <- function(.data, v) {
  .data %>% verify(sum(is.na(!! quo(v))) == 0)
}
df %>% verify_not_missing(value)

但这会引发错误:

Error in is_quosure(e2) : argument "e2" is missing, with no default 

我搜索了一些文档和 SO,包括这个问题,但一些答案提到了已弃用的部分dplyr并没有太大帮助(例如,调用vignette("nse")显示小插图不再存在)。

我在这里想念什么?


我在 x64 Linux 系统上使用 R v3.5.1、dplyr v0.7.7 和 assertr v2.5

标签: rdplyr

解决方案


有三种可能的方法来实现这一点:

第一种方法

使用eval()with substitute(),像这样:

verify_not_missing <- function(.data, v) {
  v <- eval(substitute(v), .data)
  .data %>% 
    verify(sum(is.na(v)) == 0)
}

第二种方法

使用rlang::eval_tidy()with enquo(),像这样:

verify_not_missing <- function(.data, v) {
  v <- rlang::eval_tidy(enquo(v), .data)
  .data %>% 
    verify(sum(is.na(v)) == 0)
}

第三种方法

使用!!enquo()inside select()(您需要colnames(.data)获取其他列)

verify_not_missing <- function(.data, v) {
  .data %>% 
    select(colnames(.data), v = !!enquo(v)) %>%
    verify(sum(is.na(v)) == 0)
}

df %>% verify_not_missing(value)

它们都产生相同的结果,使用您的数据,结果如下所示:

#verification [sum(is.na(v)) == 0] failed! (1 failure)

#    verb  redux_fn           predicate  column  index  value
#1 verify        NA  sum(is.na(v)) == 0      NA      1     NA

#Error: assertr stopped execution 

希望能帮助到你。


推荐阅读