我一直在阅读关于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语法更具可读性.
它可以用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()的界面也被设计成类似于其他整数函数的界面,并且可能更好地集成在转换的整齐管道中.