4

给定具有重复列名的 tibble 或 data.frame ,我想使用dplyr::renameor dplyr::rename_with
(a)用序列数字后缀('a_1''a_2'等)区分重复的名称,或者
(b)完全重命名每一列。

有:

library(tidyverse)

d <- tibble(a = 1:3, a = letters[1:3], .name_repair = "minimal")

d
# A tibble: 3 x 2
      a a    
  <int> <chr>
1     1 a    
2     2 b    
3     3 c  

想:

tibble(a_1 = 1:3, a_2 = letters[1:3])

# A tibble: 3 x 2
    a_1 a_2           # or even just: x, y    
  <int> <chr>
1     1 a    
2     2 b    
3     3 c   

期望rename/rename_with可以执行此操作似乎是合理的,尤其是因为colnames(d) <- c("a_1", "a_2")看起来很明显且不复杂。

但是到目前为止,我尝试过的三种方法都出现了不同的错误和/或意外行为:

1.使用rename(),一列重命名,另一列不重命名:

d %>% rename(x = "a", y = "a")  

# A tibble: 3 x 2
        y a    
    <int> <chr>
  1     1 a    
  2     2 b    
  3     3 c   

2.使用rename_with(),其中我使用函数添加数字后缀,我收到此错误:

d %>% rename_with(~paste(.x, 1:2, sep = "_"))

Error: Names must be unique.
x These names are duplicated:
  * "a" at locations 1 and 2.

请注意,rename_with当数据没有重复的列名时,这种使用按预期工作:

no_dupe <- tibble(a = 1:3, b = letters[1:3])
no_dupe %>% rename_with(~paste(.x, 1:2, sep = "_"))

# A tibble: 3 x 2
    a_1 b_2  
  <int> <chr>
1     1 a    
2     2 b    
3     3 c    

3.使用旧的rename_all(),我得到一个不同的错误:

d %>% rename_all(paste0, 1:2)

Error: Can't rename duplicate variables to `{name}`.

rename我在GitHub 问题中找到了关于处理重复项的讨论tidyselect但那是关于如果用户使用创建重复的列名rename()该怎么办,而不是如果他们试图取消重复该怎么办。

我是否缺少语法,或者该dplyr::rename系列没有设置为摄取重复的列名?

(我还想更好地理解为什么rename在上面的示例中只重命名一列,但这不太实用,只是我很好奇。)

提前致谢。

4

3 回答 3

2

rename不知道之前改名的事情。例如,

library(dplyr)
mtcars %>% rename(a = mpg, b = a)

错误:无法重命名不存在的列。x 列a不存在。

所以这

d %>% rename(x = "a", y = "a")  

将同一a列重命名两次,首先是x,然后是y。另一种方法是断开管道并重命名。

d %>% rename(x = "a") %>% rename(y = "a")  

# A tibble: 3 x 2
#      x y    
#  <int> <chr>
#1     1 a    
#2     2 b    
#3     3 c 

rename_with由于https://github.com/tidyverse/dplyr/blob/master/R/rename.R#L70,不允许使用重复列重命名数据框/小标题。在这种情况下,我认为您最好的选择是使用基本 R 方法。

于 2020-09-25T05:09:46.073 回答
1

试试这个:

new_names <- c('a_1', 'a_2')
names(d) <- make.unique(dput(names(d)))
d %>% 
  rename_with(~new_names)
  # rename_at(vars(names(d)), ~new_names)

出去:

    a_1 a_2  
  <int> <chr>
1     1 a    
2     2 b    
3     3 c    
于 2021-12-30T03:23:53.243 回答
0

假设您有多个列具有重复甚至一式三份的列名,您也可以尝试这种方法..

使用 获取名为 v 的向量中的所有列名colnames。之后,按照这个方法..

v <- c("a", "a", "b", "c", "c", "c", "d", "e")

df <- tibble(v)


df <- df %>% mutate(id = 1) %>% 
  group_by(v) %>% 
  summarise(id = cumsum(id)) %>% 
  mutate(v2 = paste(v,id, sep = "_")) %>%
  mutate(v2 = ifelse(id==1, v, v2)) 

最后将列名替换为df$v2

> df$v2
[1] "a"   "a_2" "b"   "c"   "c_2" "c_3" "d"   "e" 
于 2020-09-25T04:53:44.090 回答