通过在 R 中查找 table 重命名变量

Rename variables via lookup table in R

我有一个特定顺序的数据框:

df <- 
  data.frame(
    foo = 1:3,
    bar = LETTERS[1:3],
    baz = rnorm(3)
  )

df

  foo bar         baz
1   1   A  0.41474174
2   2   B -0.08416768
3   3   C -0.27931232

在另一个数据框中,我将旧变量名称与一些新名称匹配,但顺序不同:

variable_match <- 
  data.frame(
    old = names(df)[c(2, 3, 1)], 
    new = LETTERS[1:3]
  )

variable_match
  old new
1 bar   A
2 baz   B
3 foo   C

我的问题是:如何通过在第二个数据框中查找相应的值来重命名原始数据框中的变量。我正在理想地寻找 tidyverse 解决方案。我尝试了以下变体:

library(tidyverse)

df %>% rename_at(variable_match$old, funs(variable_match$new))

假设 rename_at 是正确的方法,但这行不通。我想知道 purrr::map_* 是否是正确的方法,但看不出如何。非常感谢您的建议。

这是一个单行base解决方案:

names(df2) = variable_match$new[match(names(df), variable_match$old)]

它可能不适合你 "ideal"(它不需要 tidyverse 工作),但它很简单,不需要加载任何额外的包,而是依赖于常见的内置函数。


如评论中所述,如果您更喜欢带管道的嵌套语句(管道不是为了提高可读性和防止嵌套吗?)上面的简单行等同于

library(purrr)
library(dplyr)
library(magrittr)
df = df %>%
    set_names(
        var_match %>%
        pull(new) %>%
        extract(
            names(df) %>% 
            match(var_match$old)
        )
    )

我是管道的忠实拥护者,并且 dplyr - 当事情变得更简单和更具可读性时,我一直使用它们。在这种情况下,他们采用简单的一行并将其变成一个编程难题,包括如何编写和如何阅读。

总体上更好的界面是 data.table::setnames 函数。如果转换为数据表,则代码为setnames(df, old = var_match$old, new = var_match$new)。如果不是所有名称都更改(请参阅下面的评论),这很可靠。

我将 Gregor 的答案功能化,以便在管道中轻松使用它:

lookup_rename <- function(df, column_lookup) {
  df2 <- df
  # using Gregor's answer (
  names(df2) = column_lookup$new[match(names(df), column_lookup$old)]
  df2
}

我希望这说明 base 解决方案如何在 tidyverse 哲学中轻松使用。也可能值得在函数中添加一些错误处理。