通过 dplyr relocate 在 colnames 中组织带有数字信息的列

Organize columns with numerical info in colnames via dplyr relocate

我的数据框中有大量年度数据,而且只会越来越大。我想整理一下,按列名称中包含的年份对列进行分组。

基础数据:

dput(dat)
structure(list(id = 1:2, quantity = 3:4, avg_2002 = 5:6, avg_2003 = 7:8, 
    avg_2020 = 9:10, rev_2002 = c(15L, 24L), rev_2003 = c(21L, 
    32L), rev_2020 = c(27L, 40L)), row.names = c(NA, -2L), class = "data.frame")

我想做的是将所有包含“2002”的列组织在一起,然后是“2003”列等等...我知道 relocatedplyr 中是一个很好的方法,所以我做了以下事情:

dat <- tibble(dat)
dat <- dat %>%
  relocate(grep("2002$", colnames(dat), value = TRUE),
           .before = grep("2003$", colnames(dat), value = TRUE)) %>%
  relocate(grep("2003$", colnames(dat), value = TRUE),
           .after = grep("2002$", colnames(dat), value = TRUE))

这会为我的玩具数据集生成所需的结果:

     id quantity avg_2002 rev_2002 avg_2003 rev_2003 avg_2020 rev_2020
  <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>
1     1        3        5       15        7       21        9       27
2     2        4        6       24        8       32       10       40

我的问题是:

  1. 我如何概括上面的代码,这样我就不必继续添加令人作呕的 relocate 语句?
  2. 有没有更好的方法可以不使用 dplyr::relocate 来完成这个任务?

非常感谢任何建议。谢谢!

我们可以使用 select - 提取列名称的数字部分,order 并使用 select 中的索引重新排序

library(dplyr)
dat %>% 
   select(id, quantity, order(readr::parse_number(names(.)[-(1:2)])) + 2)

-输出

# A tibble: 2 × 8
     id quantity avg_2002 rev_2002 avg_2003 rev_2003 avg_2020 rev_2020
  <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>
1     1        3        5       15        7       21        9       27
2     2        4        6       24        8       32       10       40