如何 dplyr 按列索引重命名列? [英] How to dplyr rename a column, by column index?

查看:90
本文介绍了如何 dplyr 按列索引重命名列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code renames first column in the data set:

require(dplyr)    
mtcars %>%
        setNames(c("RenamedColumn", names(.)[2:length(names(.))]))

预期结果:

                    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

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

Would it be possible to arrive at the same result using rename and column index?

这个:

mtcars %>%
    rename(1 = "ChangedNameAgain")

会失败:

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

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

Similarly trying to use rename_ or .[[1]] as column reference will return an error.

推荐答案

As of dplyr 0.7.5, rlang 0.2.1, tidyselect 0.2.4,这很简单:

As of dplyr 0.7.5, rlang 0.2.1, tidyselect 0.2.4, this simply works:

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
# ...

<小时>

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

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

The logic of rename() is new_name = old_name, so ChangedNameAgain = 1 would make more sense than 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

编辑

dplyr 的 0.6/0.7 版本开始,我还没有完全了解基于 rlang 的新 dplyr 编程系统.

I have yet to wrap my head around the new dplyr programming system based on rlang, since versions 0.6/0.7 of dplyr.

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

The underscore-suffixed version of rename used in my initial answer is now deprecated, and per @jzadra's comment, it didn't work anyway with syntactically problematic names like "foo bar".

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

Here is my attempt with the new rlang-based Non Standard Evaluation system. Do not hesitate to tell me what I've done wrong, in the comments:

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

首先我直接尝试使用 rename() 但不幸的是我遇到了错误.这似乎是一个 FIXME(或者这与 FIXME 无关?)在源代码中(我使用的是 dplyr 0.7.4),所以它可以在未来工作:

First I try directly with rename() but unfortunately I've got an error. It seems to be a FIXME (or is this FIXME unrelated?) in the source code (I'm using dplyr 0.7.4), so it could work in the future:

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

# Error: Expressions are currently not supported in `rename()`

(现在的错误消息 (dplyr 0.7.5) 读取 Error in UseMethod("rename_") : no 适用方法 for 'rename_' 应用于类function"的对象)

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

(Update 2018-06-14: df %>% rename(qux = !! quo(names(.)[[2]])) now seems to work, still with dplyr 0.7.5, not sure if an underlying package changed).

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

Here is a workaround with select that works. It doesn't preserve column order like rename though:

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

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2

如果我们想把它放在一个函数中,我们必须用 := 稍微修改它以允许在左侧取消引用.如果我们想对字符串和裸变量名等输入保持稳健,我们必须使用黑魔法"(或者说 vignette) 的 enquo()quo_name()(老实说,我不完全理解它的作用):

And if we want to put it in a function, we'd have to slightly modify it with := to allow unquoting on the left hand side. If we want to be robust to inputs like strings and bare variable names, we have to use the "dark magic" (or so says the vignette) of enquo() and quo_name() (honestly I don't fully understand what it does):

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())
}

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

This works with new name as a string:

rename_col_by_position(df, 2, "qux")

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2

这适用于作为 quosure 的新名称:

This works with new name as a quosure:

rename_col_by_position(df, 2, quo(qux))

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2

这适用于作为裸名的新名称:

This works with new name as a bare name:

rename_col_by_position(df, 2, qux)

# # A tibble: 2 x 2
#     qux   foo
#   <chr> <int>
# 1     a     1
# 2     b     2

即使这样也有效:

rename_col_by_position(df, 2, `qux quux`)

# # A tibble: 2 x 2
#   `qux quux`   foo
#        <chr> <int>
# 1          a     1
# 2          b     2

这篇关于如何 dplyr 按列索引重命名列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆