r语言 - 在"dplyr"数据管道函数中传递排序方向以"排列"



我有一个函数,可以用我的数据做很多事情。但是我想添加一个排序顺序参数,允许我在将参数传递给函数时以相反的方向一步翻转数据。并且我需要该功能与 SQL 后端兼容dbplyr.

我目前的解决方案似乎真的很不优雅。我有两个完整的数据管道,一个有desc(),一个没有。这感觉真的很笨拙,但由于我必须在dplyrdesc()包裹我的领域,我想不出还能怎么做。一个想法可能是创建一个1-1的排序参数,并在排序之前乘以我的字段。有没有更简单或更简单的方法可以做到这一点?

下面是一个简单的玩具示例,展示了我如何创建两个管道:

library(dplyr)
df <- data.frame(x = rnorm(10))
stupid_func <- function(df, sort_order = 'asc'){
## does many things in reality, this is a toy example
if (sort_order == 'asc') {
df %>% arrange(x) %>% return
} else if (sort_order == 'desc') {
df %>% arrange(desc(x)) %>% return
}
}
stupid_func(df, 'desc')
#>             x
#> 1   1.6680607
#> 2   1.4853252
#> 3   1.1468913
#> 4   1.0447893
#> 5   0.5243115
#> 6   0.3784285
#> 7  -0.5693750
#> 8  -0.8744429
#> 9  -1.0346144
#> 10 -2.6256735
stupid_func(df)
#>             x
#> 1  -2.6256735
#> 2  -1.0346144
#> 3  -0.8744429
#> 4  -0.5693750
#> 5   0.3784285
#> 6   0.5243115
#> 7   1.0447893
#> 8   1.1468913
#> 9   1.4853252
#> 10  1.6680607

这里使用了一个排序参数,该参数映射到1-1fac

stupid_func2 <- function(df, sort_order = 'asc'){
## does many things in reality
if (sort_order == 'asc') {
fac <- 1
} else {
fac <- -1
}
df %>% arrange(fac * x) %>% return
}

若要完全避免控制流,可以将descidentity作为函数而不是字符串传递并调用它:

library(dplyr)
set.seed(47)
df <- data.frame(x = rnorm(2))
f <- function(data, sort_fun = identity){
arrange(data, sort_fun(x))
}
f(df)
#>           x
#> 1 0.7111425
#> 2 1.9946963
f(df, desc)
#>           x
#> 1 1.9946963
#> 2 0.7111425

如果你真的想输入字符串,你可以使用它们来查找相应的函数,可以以相同的方式调用:

f2 <- function(data, sort_order = c('asc', 'desc')){
sort_order <- match.arg(sort_order)
sort_fun <- list(asc = identity, desc = desc)[[sort_order]]
arrange(data, sort_fun(x))
}
f2(df)
#>           x
#> 1 0.7111425
#> 2 1.9946963
f2(df, 'desc')
#>           x
#> 1 1.9946963
#> 2 0.7111425

您同样可以查找表达式,这样可以完全避免identity

f3 <- function(data, sort_order = c('asc', 'desc')){
sort_order <- match.arg(sort_order)
sort_expr <- list(asc = expr(x), desc = expr(desc(x)))[[sort_order]]
arrange(df, !!sort_expr)
}
f3(df)
#>           x
#> 1 0.7111425
#> 2 1.9946963
f3(df, 'desc')
#>           x
#> 1 1.9946963
#> 2 0.7111425

如何将 if/else 语句移动到排列函数中:

stupid_func <- function(df, ascending=TRUE){
## does many things in reality, this is a toy example
df %>% arrange(if(ascending) x else desc(x))
}
stupid_func(df)
#               x
#1  -1.4162465950
#2  -1.0428581093
#3  -0.3558181508
#4  -0.2366332875
#5   0.0003166344
#6   0.5146631983
#7   0.6390745275
#8   0.7459405376
#9   1.6161165230
#10  1.9243922633
stupid_func(df, ascending = FALSE)
#               x
#1   1.9243922633
#2   1.6161165230
#3   0.7459405376
#4   0.6390745275
#5   0.5146631983
#6   0.0003166344
#7  -0.2366332875
#8  -0.3558181508
#9  -1.0428581093
#10 -1.4162465950

最新更新