使用purrr重命名多个数据框列

6
我有以下数据帧列表,包含名为的列。
# Create 3 dataframes with identical column names
mt_list <- list(head(mtcars[, 1:2]), tail(mtcars[, 1:2]), mtcars[13:18, 1:2])
mt_list
#> [[1]]
#>                    mpg cyl
#> Mazda RX4         21.0   6
#> Mazda RX4 Wag     21.0   6
#> Datsun 710        22.8   4
#> Hornet 4 Drive    21.4   6
#> Hornet Sportabout 18.7   8
#> Valiant           18.1   6
#> 
#> [[2]]
#>                 mpg cyl
#> Porsche 914-2  26.0   4
#> Lotus Europa   30.4   4
#> Ford Pantera L 15.8   8
#> Ferrari Dino   19.7   6
#> Maserati Bora  15.0   8
#> Volvo 142E     21.4   4
#> 
#> [[3]]
#>                      mpg cyl
#> Merc 450SL          17.3   8
#> Merc 450SLC         15.2   8
#> Cadillac Fleetwood  10.4   8
#> Lincoln Continental 10.4   8
#> Chrysler Imperial   14.7   8
#> Fiat 128            32.4   4

# New 'cyl' column names to change to (they are a character vector)
new_cyl_names <- c("cyl1", "cyl2", "cyl3")
new_cyl_names
#> [1] "cyl1" "cyl2" "cyl3"

我希望将cyl命名为字符向量new_cyl_names中相应的值。
我尝试按如下方式实现:
# Custom function to change cyl to the 
# character value contained in new_colname
change_colname_cyl <- function(df, new_colname){
    df %>% 
        dplyr::rename(new_colname = cyl)
}

# The following should change the names to cyl1, cyl2, cyl3
purrr::map2(.x = mt_list, .y = new_cyl_names, ~ change_colname_cyl(.x, .y))

这导致以下结果(仅显示第一个数据框):
[[1]]
                   mpg new_colname
Mazda RX4         21.0           6
Mazda RX4 Wag     21.0           6
Datsun 710        22.8           4
Hornet 4 Drive    21.4           6
Hornet Sportabout 18.7           8
Valiant           18.1           6

请问有人能帮我正确使用purrr来实现这个目的吗?即在此情况下将cyl更改为cyl1,而不是像上面那样使用new_colname

2个回答

7

我对你的函数进行了轻微修改。我认为现在它可以工作了。请参考此链接 (https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html) 了解更多有关dplyr中标准评估和非标准评估的信息。

library(tidyverse)

# List of data frames
mt_list <- list(head(mtcars[, 1:2]), tail(mtcars[, 1:2]), mtcars[13:18, 1:2])

# New column names
new_cyl_names <- c("cyl1", "cyl2", "cyl3")

# Create the function
change_colname_cyl <- function(df, new_colname){
  df %>% rename(!!new_colname := cyl)
}

# Apply the function
map2(mt_list, new_cyl_names, ~ change_colname_cyl(.x, .y))
[[1]]
                   mpg cyl1
Mazda RX4         21.0    6
Mazda RX4 Wag     21.0    6
Datsun 710        22.8    4
Hornet 4 Drive    21.4    6
Hornet Sportabout 18.7    8
Valiant           18.1    6

[[2]]
                mpg cyl2
Porsche 914-2  26.0    4
Lotus Europa   30.4    4
Ford Pantera L 15.8    8
Ferrari Dino   19.7    6
Maserati Bora  15.0    8
Volvo 142E     21.4    4

[[3]]
                     mpg cyl3
Merc 450SL          17.3    8
Merc 450SLC         15.2    8
Cadillac Fleetwood  10.4    8
Lincoln Continental 10.4    8
Chrysler Imperial   14.7    8
Fiat 128            32.4    4

更新

根据Paul的评论,以下似乎是一种更直接和简洁的重命名列的方式。

map2(mt_list, new_cyl_names, ~rename(.x, !!.y := cyl))

2
需要 quo_name 吗?看起来 map2(mt_list, new_cyl_names, ~rename(.x, !!.y := cyl)) 可以完成同样的工作。 - Paul
@Paul 感谢您的评论。确实,在这种情况下不需要 quo_name。我已根据您的建议更新了我的帖子。 - www
@ycw。感谢您的回复 - 但是当我运行您的代码时,它会出现“错误:必须命名所有传递给rename()的参数。”。您是否也遇到了类似的错误?另外,小问题是ibrary(tidyverse)应更改为library(tidyverse)。此外,@Paul的简洁解决方案对我来说也产生了相同的错误。 - user4687531
@user4687531 感谢您指出拼写错误。我已经修复了它。不,我没有遇到这个错误。请确保您使用的是最新版本的 tidyverse - www
谢谢@ycw。我刚刚更新了“tidyverse”。我的sessionInfo()显示如下内容other attached packages: [1] dplyr_0.5.0 purrr_0.2.2 readr_1.1.0 tidyr_0.6.1 [5] tibble_1.3.3 ggplot2_2.2.1 tidyverse_1.1.1。你的情况是否一致?我仍然收到相同的错误(对于两个map2函数)。 - user4687531
1
啊,我必须手动更新 dplyr。由于某种原因,执行 install.packages("tidyverse")update.packages("tidyverse")library(tidyverse) 和重新启动 R 并没有更新 dplyr。我上面更新 dplyr 的方式有误吗?顺便说一句 - 我接受你的解决方案 :) - user4687531

4
我们可以使用来自`data.table`的`setnames`。
library(data.table)
library(tidyverse)
map2(mt_list, new_cyl_names, ~setnames(.x, 'cyl', .y))
mt_list
#[[1]]
#                   mpg cyl1
#Mazda RX4         21.0    6
#Mazda RX4 Wag     21.0    6
#Datsun 710        22.8    4
#Hornet 4 Drive    21.4    6
#Hornet Sportabout 18.7    8
#Valiant           18.1    6

#[[2]]
#                mpg cyl2
#Porsche 914-2  26.0    4
#Lotus Europa   30.4    4
#Ford Pantera L 15.8    8
#Ferrari Dino   19.7    6
#Maserati Bora  15.0    8
#Volvo 142E     21.4    4

#[[3]]
#                     mpg cyl3
#Merc 450SL          17.3    8
#Merc 450SLC         15.2    8
#Cadillac Fleetwood  10.4    8
#Lincoln Continental 10.4    8
#Chrysler Imperial   14.7    8
#Fiat 128            32.4    4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接