r-根据目标排序顺序排列数据帧行的整洁方式



早在2015年,我就提出过类似的问题,但我想找到一种整洁的方法。

这是迄今为止我能想到的最好的。这是可行的,但仅仅为了排序而更改列类型似乎是"错误的"。然而,求助于dplyr::*_join()也是如此,match()也有其自身的捕获(而且很难在整洁的上下文中使用它(。

那么,有没有一个好的/推荐的方法来做这件事呢?

定义函数

library(magrittr)
arrange_by_target <- function(
x,
targets
) {
x %>%
# Transform arrange-by columns to factors so we can leverage the order of
# the levels:
dplyr::mutate_at(
names(targets),
function(.x, .targets = targets) {
.col <- deparse(substitute(.x))
factor(.x, levels = .targets[[.col]])
}
) %>%
# Actual arranging:
dplyr::arrange_at(
names(targets)
) %>%
# Clean up by recasting factor columns to their original type:
dplyr::mutate_at(
.vars = names(targets),
function(.x, .targets = targets) {
.col <- deparse(substitute(.x))
vctrs::vec_cast(.x, to = class(.targets[[.col]]))
}
)
}

测试

x <- tibble::tribble(
~group, ~name, ~value,
"A", "B", 1,
"A", "C", 2,
"A", "A", 3,
"B", "B", 4,
"B", "A", 5
)
x %>%
arrange_by_target(
targets = list(
group = c("B", "A"),
name = c("A", "B", "C")
)
)
#> # A tibble: 5 x 3
#>   group name  value
#>   <chr> <chr> <dbl>
#> 1 B     A         5
#> 2 B     B         4
#> 3 A     A         3
#> 4 A     B         1
#> 5 A     C         2
x %>%
arrange_by_target(
targets = list(
group = c("B", "A"),
name = c("A", "B", "C") %>% rev()
)
)
#> # A tibble: 5 x 3
#>   group name  value
#>   <chr> <chr> <dbl>
#> 1 B     B         4
#> 2 B     A         5
#> 3 A     C         2
#> 4 A     B         1
#> 5 A     A         3

创建于2019-11-06由reprex包(v0.3.0(

实现这一点的最简单方法是将字符列转换为因子,如下所示:

x %>% 
mutate(
group = factor(group, c("A", "B")), 
name = factor(name, c("C", "B", "A"))
) %>% 
arrange(group, name)

我经常使用的另一个选项是使用联接。例如:

x <- tibble::tribble(
~group, ~name, ~value,
"A", "B", 1,
"A", "C", 2,
"A", "A", 3,
"B", "B", 4,
"B", "A", 5,
"A", "A", 6,
"B", "C", 7,
"A", "B", 8,
"B", "B", 9
)
custom_sort <- tibble::tribble(
~group, ~name,
"A", "C",
"A", "B",
"A", "A",
"B", "B",
"B", "A"
)
x %>% right_join(custom_sort)

最新更新