在dplyr而不是SE中使用get()是否有缺点?

Tho*_*mas 7 r dplyr

我一直在阅读关于dplyr中的SE和NSE,并且遇到了我实际需要SE的问题.我有以下函数,应该找到一些项匹配的行,但目标变量不:

find_dataset_inconsistencies <- function(df, target_column, cols_to_use) {
  inconsists <- df %>% 
    group_by_at(cols_to_use) %>% 
    summarise(uTargets = length(unique(get(target_column)))) %>% 
    filter(uTargets > 1)
}
Run Code Online (Sandbox Code Playgroud)

这似乎适用于我的情况.但是,get(target_column)是一种解决方法,因为我需要变量的SE而不能对列名进行硬编码.我最初尝试使用SE版本(summarise_(.dots = ...)),但无法找到用于评估target_column的正确语法.

我的问题如下:简单使用有什么缺点get()吗?这是不行的吗?任何风险/减速?简单地使用get肯定比"正确的"SE语法更具可读性.

Aur*_*èle 5

它可以用NSE来完成rlang.

假设您的用例是:

find_dataset_inconsistencies(mtcars, "mpg", c("cyl", "vs", "am", "gear", "carb"))
# # A tibble: 8 x 6
# # Groups:   cyl, vs, am, gear [5]
#     cyl    vs    am  gear  carb uTargets
#   <dbl> <dbl> <dbl> <dbl> <dbl>    <int>
# 1  4.00  1.00  0     4.00  2.00        2
# 2  4.00  1.00  1.00  4.00  1.00        4
# 3  4.00  1.00  1.00  4.00  2.00        2
# 4  6.00  1.00  0     3.00  1.00        2
# 5  6.00  1.00  0     4.00  4.00        2
# 6  8.00  0     0     3.00  2.00        4
# 7  8.00  0     0     3.00  3.00        3
# 8  8.00  0     0     3.00  4.00        4
Run Code Online (Sandbox Code Playgroud)

你可以:

library(dplyr)

f2 <- function(df, target_column, cols_to_use) {
  group_by_at(df, cols_to_use) %>% 
    summarise(uTargets = n_distinct(!! rlang::sym(target_column))) %>% 
    filter(uTargets > 1)
}

all.equal(
  find_dataset_inconsistencies(mtcars, "mpg", c("cyl", "vs", "am", "gear", "carb")),
  f2(mtcars, "mpg", c("cyl", "vs", "am", "gear", "carb"))
)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

关于风险问题的实际答案:

现在想象一下foo <- 3,你的全球环境.相比:

find_dataset_inconsistencies(mtcars, "foo", c("cyl", "vs", "am", "gear", "carb"))
# A tibble: 0 x 6
# Groups:   cyl, vs, am, gear [0]
# ... with 6 variables: cyl <dbl>, vs <dbl>, am <dbl>, gear <dbl>,
#   carb <dbl>, uTargets <int>
Run Code Online (Sandbox Code Playgroud)

它将静默返回一个空数据框,并:

f2(mtcars, "foo", c("cyl", "vs", "am", "gear", "carb"))
# Error in summarise_impl(.data, dots) : variable 'foo' not found
Run Code Online (Sandbox Code Playgroud)

这将引发一个直接指向错误的错误.


编辑

既然你似乎是在"整齐的方式"之后,我会推荐以下内容.潜在的哲学似乎是尽可能地阻止变量名称作为字符串使用,而不是作为裸名称:

f3 <- function(df, target_column, ...) {
  target_column <- enquo(target_column)
  cols_to_use <- quos(...)
  group_by(df, !!! cols_to_use) %>% 
    summarise(uTargets = n_distinct(!! target_column)) %>% 
    filter(uTargets > 1)
}
all.equal(
  find_dataset_inconsistencies(mtcars, "mpg", c("cyl", "vs", "am", "gear", "carb")),
  f3(mtcars, target_column = mpg, cyl, vs, am, gear, carb)
)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

f3()的界面也被设计成类似于其他整数函数的界面,并且可能更好地集成在转换的整齐管道中.

  • `get(target_column,df)`忽略数据帧的分组. (3认同)