使用非标准评估按多列排序
Order by multiple columns using non-standard evaluation
假设我想使用多列并使用非标准进化来订购 data.frame
。我可能有一个看起来像这样的函数
my_order <- function(data, ...) {
with(data, order(...))
}
我在使用此函数时遇到错误,因为我的列未在 with
的上下文中计算。
my_order(mtcars, mpg, cyl)
# Error in order(...) : object 'mpg' not found
注意:我不希望使用 dplyr::arrange()
来解决这个问题,因为它增加了依赖性。
这是使用基数 R 传递未解析符号的一种方法
my_order <- function(data, ...) {
dots <- substitute(...())
with(data, do.call("order", as.list(dots)))
}
my_order(mtcars, mpg, cyl)
基本上我们使用 substitute 来捕获符号名称,然后使用 do.call
将它们注入到对 order
.
的调用中
或者您可以考虑重新编写对函数的调用并更改评估环境
my_order <- function(data, ...) {
call <-match.call()
call[[1]] <- quote(order)
call[2] <- NULL
eval(call, data, parent.frame())
}
my_order(mtcars, mpg, cyl)
一个选项是将表达式包装成 eval.parent(substitute(...))
:
my_order <- function( data, ... ) {
eval.parent(substitute( with(data, order(...)) ))
}
my_order( mtcars, cyl, mpg )
# [1] 32 21 3 9 8 27 26 19 28 18 20 11 6 10 30 1 2 4 15 16 24 7 17 31 14
# [26] 23 22 29 12 13 5 25
请注意,我们使用 eval.parent()
而不是 eval()
,因为 . The eval.parent()
trick has been 是解决此问题的一种方式,并允许我们在其他函数中无缝使用 my_order()
,包括 magrittr 管道:
mtcars %>% my_order(cyl)
# [1] 3 8 9 18 19 20 21 26 27 28 32 1 2 4 6 10 11 30 5 7 12 13 14 15 16
# [26] 17 22 23 24 25 29 31
假设我想使用多列并使用非标准进化来订购 data.frame
。我可能有一个看起来像这样的函数
my_order <- function(data, ...) {
with(data, order(...))
}
我在使用此函数时遇到错误,因为我的列未在 with
的上下文中计算。
my_order(mtcars, mpg, cyl)
# Error in order(...) : object 'mpg' not found
注意:我不希望使用 dplyr::arrange()
来解决这个问题,因为它增加了依赖性。
这是使用基数 R 传递未解析符号的一种方法
my_order <- function(data, ...) {
dots <- substitute(...())
with(data, do.call("order", as.list(dots)))
}
my_order(mtcars, mpg, cyl)
基本上我们使用 substitute 来捕获符号名称,然后使用 do.call
将它们注入到对 order
.
或者您可以考虑重新编写对函数的调用并更改评估环境
my_order <- function(data, ...) {
call <-match.call()
call[[1]] <- quote(order)
call[2] <- NULL
eval(call, data, parent.frame())
}
my_order(mtcars, mpg, cyl)
一个选项是将表达式包装成 eval.parent(substitute(...))
:
my_order <- function( data, ... ) {
eval.parent(substitute( with(data, order(...)) ))
}
my_order( mtcars, cyl, mpg )
# [1] 32 21 3 9 8 27 26 19 28 18 20 11 6 10 30 1 2 4 15 16 24 7 17 31 14
# [26] 23 22 29 12 13 5 25
请注意,我们使用 eval.parent()
而不是 eval()
,因为 eval.parent()
trick has been my_order()
,包括 magrittr 管道:
mtcars %>% my_order(cyl)
# [1] 3 8 9 18 19 20 21 26 27 28 32 1 2 4 6 10 11 30 5 7 12 13 14 15 16
# [26] 17 22 23 24 25 29 31