`dplyr::select` 无需对列重新排序

Ken*_*osu 6 r dplyr

我正在寻找一种简单、简洁的使用方法,dplyr::select无需重新排列列。

\n

考虑这个数据集:

\n
library(tidyverse)\nhead(msleep)\n#> # A tibble: 6 \xc3\x97 11\n#>   name    genus vore  order conservation sleep_total sleep_rem sleep_cycle awake\n#>   <chr>   <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>\n#> 1 Cheetah Acin\xe2\x80\xa6 carni Carn\xe2\x80\xa6 lc                  12.1      NA        NA      11.9\n#> 2 Owl mo\xe2\x80\xa6 Aotus omni  Prim\xe2\x80\xa6 <NA>                17         1.8      NA       7  \n#> 3 Mounta\xe2\x80\xa6 Aplo\xe2\x80\xa6 herbi Rode\xe2\x80\xa6 nt                  14.4       2.4      NA       9.6\n#> 4 Greate\xe2\x80\xa6 Blar\xe2\x80\xa6 omni  Sori\xe2\x80\xa6 lc                  14.9       2.3       0.133   9.1\n#> 5 Cow     Bos   herbi Arti\xe2\x80\xa6 domesticated         4         0.7       0.667  20  \n#> 6 Three-\xe2\x80\xa6 Brad\xe2\x80\xa6 herbi Pilo\xe2\x80\xa6 <NA>                14.4       2.2       0.767   9.6\n#> # \xe2\x80\xa6 with 2 more variables: brainwt <dbl>, bodywt <dbl>\n
Run Code Online (Sandbox Code Playgroud)\n

如果我选择voregenusname,则生成的数据框将按照提供列的顺序排列。

\n
msleep %>% select(vore, genus, name)\n#> # A tibble: 83 \xc3\x97 3\n#>    vore  genus       name                      \n#>    <chr> <chr>       <chr>                     \n#>  1 carni Acinonyx    Cheetah                   \n#>  2 omni  Aotus       Owl monkey                \n#>  3 herbi Aplodontia  Mountain beaver           \n#>  4 omni  Blarina     Greater short-tailed shrew\n#>  5 herbi Bos         Cow                       \n#>  6 herbi Bradypus    Three-toed sloth          \n#>  7 carni Callorhinus Northern fur seal         \n#>  8 <NA>  Calomys     Vesper mouse              \n#>  9 carni Canis       Dog                       \n#> 10 herbi Capreolus   Roe deer                  \n#> # \xe2\x80\xa6 with 73 more rows\n
Run Code Online (Sandbox Code Playgroud)\n

相反,我想将它们保留为默认顺序:namegenus、 然后vore

\n

我有一个解决方案(见下文),但我不喜欢它,因为它非常冗长,而且不完全 \xe2\x80\x9ctidyverse-esque\xe2\x80\x9d。\n(我正在教授 tidyverse 课程简介,并且想要一些不会吓到初学者的东西。)

\n
msleep %>% \n  select(all_of(names(msleep)[names(msleep) %in% c("vore", "genus", "name")]))\n#> # A tibble: 83 \xc3\x97 3\n#>    name                       genus       vore \n#>    <chr>                      <chr>       <chr>\n#>  1 Cheetah                    Acinonyx    carni\n#>  2 Owl monkey                 Aotus       omni \n#>  3 Mountain beaver            Aplodontia  herbi\n#>  4 Greater short-tailed shrew Blarina     omni \n#>  5 Cow                        Bos         herbi\n#>  6 Three-toed sloth           Bradypus    herbi\n#>  7 Northern fur seal          Callorhinus carni\n#>  8 Vesper mouse               Calomys     <NA> \n#>  9 Dog                        Canis       carni\n#> 10 Roe deer                   Capreolus   herbi\n#> # \xe2\x80\xa6 with 73 more rows\n
Run Code Online (Sandbox Code Playgroud)\n

有这样的事吗?谢谢你!

\n

对于上下文:实际上,我们有一个包含大约 400 列的数据框,我们一次从中选择 ~10-20 列进行处理。原始数据框中的列顺序是有意义的,但我们不想费力地在 select 语句中以正确的顺序列出它们。我承认这是一个非常具体的需求。

\n

由reprex 包于 2021 年 12 月 22 日创建(v2.0.1)

\n

小智 2

您可以使用 的强大功能eval_select()来创建一个函数来选择列并对列进行排序。

library(dplyr)

select_in_order <- function(data, ...) {
  ordered_cols <- sort(tidyselect::eval_select(expr(c(...)), data))
  select(data, ordered_cols)
}
Run Code Online (Sandbox Code Playgroud)

所以现在这将满足您的要求。好处是,它将是您习惯于输入语句的“全部功能” select()

# library(ggplot2) # msleep is in ggplot2

msleep %>%
  select_in_order(vore, genus, name)

# this will work as well
msleep %>%
  select_in_order(starts_with("sleep"), vore, name:genus)
Run Code Online (Sandbox Code Playgroud)

编辑

作为另一种选择,只需relocate()在您的陈述后使用即可select()。这种替代方法实现了以初学者易于理解的方式保持列有序的最终目标。

msleep %>%
  select(vore, genus, name) %>%
  relocate(any_of(names(msleep)))
Run Code Online (Sandbox Code Playgroud)