我有一个特定顺序的数据框:
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_*
是否是正确的方法,但不知道如何。非常感谢您的建议。
答案 0 :(得分:6)
以下是单行base
解决方案:
names(df2) = variable_match$new[match(names(df), variable_match$old)]
它可能不是理想的&#34;对你而言(它不需要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)
。如果并非所有名称都被更改,这是强大的(请参阅下面的评论)。
答案 1 :(得分:2)
我将Gregor的答案功能化,因此可以在管道中轻松使用:
lookup_rename <- function(df, column_lookup) {
df2 <- df
# using Gregor's answer (https://stackoverflow.com/a/43742442/3927208)
names(df2) = column_lookup$new[match(names(df), column_lookup$old)]
df2
}
我希望这能说明base
解决方案如何在tidyverse
哲学中轻松使用。可能值得为函数添加一些错误处理。