按名称重命名多个列

qoh*_*eth 63 r rename dataframe r-faq

有人应该已经问过这个,但我找不到答案.说我有:

x = data.frame(q=1,w=2,e=3, ...and many many columns...)  
Run Code Online (Sandbox Code Playgroud)

将我不一定知道的位置的任意子列重命名为其他任意名称的最优雅方法是什么?

例如说我要重新命名"q""e""A""B",什么是最优雅的代码来做到这一点?

显然,我可以做一个循环:

oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有更好的方法?也许使用一些包?(plyr::rename等)

mne*_*nel 87

setnamesdata.table包中可以使用data.frames或data.tables

library(data.table)
d <- data.frame(a=1:2,b=2:3,d=4:5)
setnames(d, old = c('a','d'), new = c('anew','dnew'))
d


 #   anew b dnew
 # 1    1 2    4
 # 2    2 3    5
Run Code Online (Sandbox Code Playgroud)

请注意,更改是通过引用进行的,因此不进行复制(即使对于data.frames!)

  • 对于迟到的人 - 另请参阅下面的 [Joel 的回答](http://stackoverflow.com/a/36010381/4606130),其中介绍了检查现有列,以防您有一个名称更改列表,其中可能并非全部都是存在例如 `old = c("a", "d", "e")` (2认同)
  • @micstr `skip_absent=TRUE` :) (2认同)

Gor*_*rka 65

使用dplyr,您可以:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

df %>% rename(A = q, B = e)

#  A w B
#1 1 2 3
Run Code Online (Sandbox Code Playgroud)

或者如果你想使用载体,正如@ Jelena-bioinf所建议的那样:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

oldnames = c("q","e")
newnames = c("A","B")

df %>% rename_at(vars(oldnames), ~ newnames)

#  A w B
#1 1 2 3
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@ Jelena-bioinf.我修改了答案,包括你的建议. (3认同)
  • 我想,用户询问将'old`和`new`名称作为向量传递 (2认同)
  • `rename_with` 可以使用函数或公式来重命名作为 `.cols` 参数给出的所有列。例如 `rename_with(iris, toupper,starts_with("Petal"))` 相当于 `rename_with(iris, ~ toupper(.x),starts_with("Petal"))` 。 (2认同)

Agi*_*ean 32

更新 dplyr 1.0.0

最新的 dplyr 版本通过添加rename_with()where_with 引用函数作为输入而变得更加灵活。诀窍是将字符向量重新表述newnames公式 (by ~),因此它相当于function(x) return (newnames)

在我主观看来,这是最优雅的 dplyr 表达方式。更新:感谢@desval,oldnames 向量必须包含在其中all_of以包含其所有元素:

# shortest & most elegant expression
df %>% rename_with(~ newnames, all_of(oldnames))

A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)

边注:

如果颠倒顺序,则必须指定任一参数 .fn,因为 .fn 应该在 .cols 参数之前:

df %>% rename_with(oldnames, .fn = ~ newnames)

A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)

或指定参数 .col:

 df %>% rename_with(.col = oldnames, ~ newnames)

A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)

  • 看起来这个答案目前返回一个警告,并且将来会返回一个错误,因为在 select https://tidyselect.r-lib.org/reference/faq-external-vector 中使用外部向量时存在歧义.html。这应该可以修复它 ```df %&gt;% rename_with(~ newnames, all_of(oldnames))``` (3认同)

Jaa*_*aap 31

另一个不太大的数据帧解决方案是(基于@thelatemail答案):

x <- data.frame(q=1,w=2,e=3)

> x
  q w e
1 1 2 3

colnames(x) <- c("A","w","B")

> x
  A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用:

names(x) <- c("C","w","D")

> x
  C w D
1 1 2 3
Run Code Online (Sandbox Code Playgroud)

此外,您还可以重命名列名的子集:

names(x)[2:3] <- c("E","F")

> x
  C E F
1 1 2 3
Run Code Online (Sandbox Code Playgroud)


Mat*_*cho 15

这是我发现使用组合purrr::set_names()和一些stringr操作重命名多个列的最有效方法.

library(tidyverse)

# Make a tibble with bad names
data <- tibble(
    `Bad NameS 1` = letters[1:10],
    `bAd NameS 2` = rnorm(10)
)

data 
# A tibble: 10 x 2
   `Bad NameS 1` `bAd NameS 2`
   <chr>                 <dbl>
 1 a                    -0.840
 2 b                    -1.56 
 3 c                    -0.625
 4 d                     0.506
 5 e                    -1.52 
 6 f                    -0.212
 7 g                    -1.50 
 8 h                    -1.53 
 9 i                     0.420
 10 j                     0.957

# Use purrr::set_names() with annonymous function of stringr operations
data %>%
    set_names(~ str_to_lower(.) %>%
                  str_replace_all(" ", "_") %>%
                  str_replace_all("bad", "good"))

# A tibble: 10 x 2
   good_names_1 good_names_2
   <chr>               <dbl>
 1 a                  -0.840
 2 b                  -1.56 
 3 c                  -0.625
 4 d                   0.506
 5 e                  -1.52 
 6 f                  -0.212
 7 g                  -1.50 
 8 h                  -1.53 
 9 i                   0.420
10 j                   0.957
Run Code Online (Sandbox Code Playgroud)

  • 这应该是答案,但是您可能还应该扩展set_names()管道中的〜和。参数。 (3认同)
  • @DaveRGP 当使用 `purrr` 函数时,波形符 `~` 表示“对于每一列”。`.` 是 LHS = 管道左侧的 dplyr 语法,即对通过管道传输的对象的引用,在本例中为“data”。 (2认同)

Joe*_*per 11

所以我最近遇到了这个问题,如果您不确定列是否存在并且只想重命名那些:

existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
Run Code Online (Sandbox Code Playgroud)


Tje*_*ebo 8

您可以使用命名向量。下面两个选项(带有基本 R 和 dplyr)。

基 R,通过子集化:

x = data.frame(q = 1, w = 2, e = 3) 

rename_vec <- c(q = "A", e = "B")
## vector of same length as names(x) which returns NA if there is no match to names(x)
which_rename <- rename_vec[names(x)]
## simple ifelse where names(x) will be renamed for every non-NA 
names(x) <- ifelse(is.na(which_rename), names(x), which_rename)

x
#>   A w B
#> 1 1 2 3
Run Code Online (Sandbox Code Playgroud)

或者一个dplyr选项!!!

library(dplyr)

rename_vec <- c(A = "q", B = "e") # the names are just the other way round than in the base R way!

x %>% rename(!!!rename_vec)
#>   A w B
#> 1 1 2 3
Run Code Online (Sandbox Code Playgroud)

后者之所以有效,是因为“大爆炸”运算!!!符强制评估列表或向量。

?`!!`

!!! 强制拼接对象列表。列表的元素被拼接到位,这意味着它们每个都成为一个参数。


Jam*_*ing 5

names(x)[names(x) %in% c("q","e")]<-c("A","B")
Run Code Online (Sandbox Code Playgroud)

  • 不完全是,因为正如我所说,我不一定知道列的位置,您的解决方案仅在对 `oldnames` 进行排序时才有效,以便 `oldnames[i]` 出现在 i&lt;j 的 `oldnames[j]` 之前. (4认同)

the*_*ail 5

建立在@ user3114046的答案上:

x <- data.frame(q=1,w=2,e=3)
x
#  q w e
#1 1 2 3

names(x)[match(oldnames,names(x))] <- newnames

x
#  A w B
#1 1 2 3
Run Code Online (Sandbox Code Playgroud)

这不依赖于x数据集中列的特定顺序.


Pau*_*eux 5

dplyr::rename_with已经有一些答案提到了这些功能rlang::set_names。他们是分开的。这个答案说明了两者之间的差异以及使用函数和公式来重命名列。

rename_withdplyr包中可以使用函数或公式来重命名作为.cols参数给出的所选列。例如传递函数名称toupper

library(dplyr)
rename_with(head(iris), toupper, starts_with("Petal"))
Run Code Online (Sandbox Code Playgroud)

相当于传递公式~ toupper(.x)

rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))
Run Code Online (Sandbox Code Playgroud)

重命名所有列时,您还可以使用set_namesrlang 包中的内容。为了制作一个不同的示例,让我们使用paste0重命名函数。pasteO接受 2 个参数,因此根据我们使用的是函数还是公式,有不同的方法来传递第二个参数。

rlang::set_names(head(iris), paste0, "_hi")
rlang::set_names(head(iris), ~ paste0(.x, "_hi"))
Run Code Online (Sandbox Code Playgroud)

rename_with通过将数据帧作为第一个参数.data、函数作为第二个参数.fn、所有列作为第三个参数.cols=everything()、函数参数作为第四个参数来实现相同的效果...。或者,您可以将第二个、第三个和第四个参数放入作为第二个参数给出的公式中。

rename_with(head(iris), paste0, everything(), "_hi")
rename_with(head(iris), ~ paste0(.x, "_hi"))
Run Code Online (Sandbox Code Playgroud)

rename_with仅适用于数据框。set_names更通用,还可以进行向量重命名

rlang::set_names(1:4, c("a", "b", "c", "d"))
Run Code Online (Sandbox Code Playgroud)