如何通过列索引dplyr重命名列?

Kon*_*rad 17 r rename dataframe dplyr nse

以下代码重命名数据集中的第一列:

require(dplyr)    
mtcars %>%
        setNames(c("RenamedColumn", names(.)[2:length(names(.))]))
Run Code Online (Sandbox Code Playgroud)

期望的结果:

                    RenamedColumn cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4                    21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag                21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710                   22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Run Code Online (Sandbox Code Playgroud)

是否可以使用和列索引得到相同的结果rename

这个:

mtcars %>%
    rename(1 = "ChangedNameAgain")
Run Code Online (Sandbox Code Playgroud)

将失败:

Error in source("~/.active-rstudio-document", echo = TRUE) : 
  ~/.active-rstudio-document:7:14: unexpected '='
6: mtcars %>%
7:     rename(1 =
                ^
Run Code Online (Sandbox Code Playgroud)

同样,尝试使用rename_.[[1]]作为列引用将返回错误.

Aur*_*èle 32

由于dplyr 0.7.5,rlang 0.2.1,tidyselect 0.2.4,这只是工作:

library(dplyr)

rename(mtcars, ChangedNameAgain = 1)

#                     ChangedNameAgain cyl  disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4                       21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag                   21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710                      22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Hornet 4 Drive                  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Hornet Sportabout               18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# ...
Run Code Online (Sandbox Code Playgroud)

原始答案和编辑现已过时:

逻辑rename()new_name = old_name,所以ChangedNameAgain = 1更有意义1 = ChangedNameAgain.

我会建议:

mtcars %>% rename_(ChangedNameAgain = names(.)[1])
#                     ChangedNameAgain cyl  disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4                       21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag                   21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710                      22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Hornet 4 Drive                  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Hornet Sportabout               18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# Valiant                         18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Run Code Online (Sandbox Code Playgroud)

编辑

我还没有围绕新的dplyr编程系统rlang,因为版本0.6/0.7 dplyr.

rename在我的初始答案中使用的下划线后缀版本现在已被弃用,并且根据@ jzadra的评论,它无论如何都不能用于语法上有问题的名称"foo bar".

以下是我对rlang基于新的非标准评估系统的尝试.在评论中,不要犹豫告诉我我做错了什么:

df <- tibble("foo" = 1:2, "bar baz" = letters[1:2])

# # A tibble: 2 x 2
#     foo `bar baz`
#   <int>     <chr>
# 1     1         a
# 2     2         b
Run Code Online (Sandbox Code Playgroud)

首先我直接尝试,rename()但不幸的是我有一个错误.它似乎FIXME是源代码中的一个(或者这个FIXME无关吗?)(我使用的是dplyr0.7.4),所以它可以在以后工作:

df %>% rename(qux = !! quo(names(.)[[2]]))

# Error: Expressions are currently not supported in `rename()`
Run Code Online (Sandbox Code Playgroud)

(编辑:现在的错误信息(dplyr 0.7.5)读取Error in UseMethod("rename_") : no applicable method for 'rename_' applied to an object of class "function")

(更新2018-06-14:df %>% rename(qux = !! quo(names(.)[[2]]))现在似乎工作,仍然使用dplyr 0.7.5,不确定底层包是否更改).

这是一个有效的解决方法select.它不像以下那样保留列顺序rename:

df %>% select(qux = !! quo(names(.)[[2]]), everything())

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2
Run Code Online (Sandbox Code Playgroud)

如果我们想把它放在一个函数中,我们必须稍微修改它:=以允许在左侧进行取消引用.如果我们想要像字符串和裸变量名这样的输入,那么我们必须使用"黑魔法"(或者说是小插图)enquo()quo_name()(老实说,我并不完全理解它的作用):

rename_col_by_position <- function(df, position, new_name) {
  new_name <- enquo(new_name)
  new_name <- quo_name(new_name)
  select(df, !! new_name := !! quo(names(df)[[position]]), everything())
}
Run Code Online (Sandbox Code Playgroud)

这适用于新名称作为字符串:

rename_col_by_position(df, 2, "qux")

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2
Run Code Online (Sandbox Code Playgroud)

这适用于新名称作为一个quosure:

rename_col_by_position(df, 2, quo(qux))

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2
Run Code Online (Sandbox Code Playgroud)

这适用于新名称作为一个裸名称:

rename_col_by_position(df, 2, qux)

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2
Run Code Online (Sandbox Code Playgroud)

甚至这个工作:

rename_col_by_position(df, 2, `qux quux`)

# # A tibble: 2 x 2
#   `qux quux`   foo
#        <chr> <int>
# 1          a     1
# 2          b     2
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.我必须同意,新的rlang已经从一个可理解的语法中取出了一个可以理解的语法,这对我来说似乎是一个倒退. (2认同)

Art*_*lov 7

这里有几个替代解决方案,可以说更容易阅读,因为它们并不关注.参考.select理解列索引,所以如果你重命名第一列,你可以简单地做

mtcars %>% select( RenamedColumn = 1, everything() )
Run Code Online (Sandbox Code Playgroud)

但是,使用的问题select是,如果您在中间重命名列,它将重新排序列.要解决此问题,您必须预先选择要重命名的列的左侧列:

## This will rename the 7th column without changing column order
mtcars %>% select( 1:6, RenamedColumn = 7, everything() )
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用new rename_at,它也理解列索引:

## This will also rename the 7th column without changing the order
## Credit for simplifying the second argument: Moody_Mudskipper
mtcars %>% rename_at( 7, ~"RenamedColumn" )
Run Code Online (Sandbox Code Playgroud)

~是必要的,因为rename_at它非常灵活,可以接受函数作为其第二个参数.例如,mtcars %>% rename_at( c(2,4), toupper )将使第二列和第四列的名称为大写.


小智 6

dplyr已所取代rename_at()rename_with()。您可以通过索引重命名列,如下所示:

library(tidyverse)

mtcars %>% 
  rename_with(.cols = 1, ~"renamed_column")

#>                     renamed_column cyl  disp  hp drat    wt  qsec vs am gear
#> Mazda RX4                    21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
#> Mazda RX4 Wag                21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
#> Datsun 710                   22.8   4 108.0  93 3.85 2.320 18.61  1  1    4
#> Hornet 4 Drive               21.4   6 258.0 110 3.08 3.215 19.44  1  0    3
#> Hornet Sportabout            18.7   8 360.0 175 3.15 3.440 17.02  0  0    3
#> ...
Run Code Online (Sandbox Code Playgroud)

确保~在新列名称之前包含波浪号 ( )*。

另请注意,如果您引入该glue包,您可以像这样修改现有的列名:

library(glue)

mtcars %>% 
  rename_with(.cols = 1, ~glue::glue("renamed_{.}"))
#>                     renamed_mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4                  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag              21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> Datsun 710                 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> Hornet 4 Drive             21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> Hornet Sportabout          18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> ...
Run Code Online (Sandbox Code Playgroud)

将上述方法应用于多列只是使用冒号 ( :)传入列索引号范围或使用c();在向量中传递多个索引的问题。这是两者的结合:

mtcars %>% 
  rename_with(.cols = c(1:3, 5), ~glue::glue("renamed_{.}"))
#>                     renamed_mpg renamed_cyl renamed_disp  hp renamed_drat    wt
#> Mazda RX4                  21.0           6        160.0 110         3.90 2.620
#> Mazda RX4 Wag              21.0           6        160.0 110         3.90 2.875
#> Datsun 710                 22.8           4        108.0  93         3.85 2.320
#> Hornet 4 Drive             21.4           6        258.0 110         3.08 3.215
#> Hornet Sportabout          18.7           8        360.0 175         3.15 3.440
#> ...
Run Code Online (Sandbox Code Playgroud)

请记住,由于.代表当前列名,您可以像这样对它应用字符串修改函数:

mtcars %>% 
  rename_with(.cols = c(1:3), 
              ~glue::glue("renamed_{str_replace(.,'mpg','miles_per_gallon')}"))
#>                     renamed_miles_per_gallon renamed_cyl renamed_disp  hp
#> Mazda RX4                               21.0           6        160.0 110
#> Mazda RX4 Wag                           21.0           6        160.0 110
#> Datsun 710                              22.8           4        108.0  93
#> Hornet 4 Drive                          21.4           6        258.0 110
#> Hornet Sportabout                       18.7           8        360.0 175
#> ...
Run Code Online (Sandbox Code Playgroud)

*您可以在此处了解有关~.NSE 函数速记的更多信息。