我的目标是编写一个take_by_rank
函数
- 可以对数据框中任意选择的数字列进行操作;
- 使用非标准评估,如
base::subset
或dplyr
动词; - 自然理解减号,所以这
-foo
意味着“最大的值得foo
到最低的等级”; n
按总排名返回顶部或底部行,这是为每个选定变量计算的排名总和。
我对学习最新的dplyr 方法和寻找替代方法都很感兴趣,即对包选择没有限制(纯base
或data.table
可能?)。
我目前的解决方案是
library(data.table)
library(dplyr)
library(rlang)
take_by_rank <- function(df, ..., n = 100) {
selected_vars <- quos(...)
if (!length(selected_vars))
stop("No variables to rank!")
prefix <- ".rank_"
for (i in seq_along(selected_vars)) {
rank_name <- paste0(prefix, quo_name(selected_vars[[i]]))
df <- df %>%
mutate(!!rank_name := frankv(!!selected_vars[[i]]))
}
df %>%
mutate(TotalRank = rowSums(select(df, starts_with(prefix)))) %>%
arrange(TotalRank) %>%
top_n(n, -TotalRank)
}
这似乎没问题,但也许我错过了更直接的东西。如果有办法替换 for 循环,那也很好。
使用示例(供参考)
take_by_rank(mtcars, mpg, qsec, n = 3)
mpg cyl disp hp drat wt qsec vs am gear carb .rank_mpg .rank_qsec TotalRank
1 13.3 8 350 245 3.73 3.84 15.41 0 0 3 4 3 3 6
2 15.0 8 301 335 3.54 3.57 14.60 0 1 5 8 6 2 8
3 14.3 8 360 245 3.21 3.57 15.84 0 0 3 4 4 5 9
take_by_rank(mtcars, mpg, qsec, n = -3)
mpg cyl disp hp drat wt qsec vs am gear carb .rank_mpg .rank_qsec TotalRank
1 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 24.5 32 56.5
2 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 31.0 27 58.0
3 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 32.0 28 60.0
take_by_rank(mtcars, mpg, -qsec, n = 3)
mpg cyl disp hp drat wt qsec vs am gear carb .rank_mpg .rank_-qsec TotalRank
1 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 14.0 2 16.0
2 10.4 8 472 205 2.93 5.250 17.98 0 0 3 4 1.5 15 16.5
3 10.4 8 460 215 3.00 5.424 17.82 0 0 3 4 1.5 16 17.5