如何删除 tidyverse 中 tibble 中的重复列

How to delete duplicated columns in a tibble in the tidyverse

假设我的数据有两个相同的列,称为 SYC SJ Equity。当我使用基数 read.csv() 并将 check.names 设置为 FALSE 将其导入 R 时,数据将导入两列名称相同的列。然后我可以像这样删除重复的列:

df <- df %>% 
  do(.[!duplicated(names(.))])

如果我使用 readr 中的 read_csv() 函数导入数据,重复的列将以 "SYC SJ Equity_1" 的形式获取列名。然后我可以执行以下操作来删除重复的列

df <- df %>%
  select(-contains("_"))

但是,如果数据采用 .xlsx 格式的 sheet,并且我使用 readxl 包中的 read_excel() 函数,则重复的列得到导入为:

New names:
* `SYC SJ Equity` -> `SYC SJ Equity...406`
* `SYC SJ Equity` -> `SYC SJ Equity...407`

在这种情况下,两列都被重命名,而在 read_csv() 中,只有额外的实例被重命名。在这种情况下,我必须匹配整个字符串才能删除重复的列。我不知道哪些数字将分配给重复的列。我假设它基于列索引?此外,即使使用 read_csv() 导入,如果我的列在原始数据中的名称中自然都有下划线,我的解决方案也不会起作用。所以我的问题是,如何删除 tidyverse 中的重复列,其中数据存储在 tibbles 中?使用 base R 很容易,使用 duplicated()。但这不适用于 tidyverse 的小标题。我知道 dplyr 动词 select 按列名而不是按列索引,因此列名必须始终不同。但是有没有一种方法可以始终使用 tidyverse 删除重复的列,而无需查看控制台以查看新的重复名称?

假设您没有任何名称实际包含 3 个点 (...) 的列。我们可以将数据读入 R 并从名称中删除这 3 个点,使用 duplicated 查找重复名称和 select 唯一列。

df[, !duplicated(sub("\.\.\..*", "", names(df)))]

只是为了展示它如何在向量上工作

x <- c("y", "SYC SJ Equity...406", "SYC SJ Equity...407", "x")
x[!duplicated(sub("\.\.\..*", "", x))]
#[1] "y"                   "SYC SJ Equity...406" "x"

所以它保持 "x""y" 列不变,select 只保留第一个重复值。

根据 Ronak 提供的答案,如果您想在 dplyr 中执行此操作,那么您可以将他提供的解决方案与 select_if 一起使用。

library(dplyr)

df <- data.frame("x" = runif(3),
                 "SYC SJ Equity...406" = c("a", "a", "b"), 
                 "SYC SJ Equity...407" = c("a", "a", "b"), 
                 "y" = runif(3))

df %>%
  select_if(!duplicated(sub("\.\.\..*", "", names(.))))

select_ifstr_remove

library(stringr)
library(dplyr)
df %>% 
    select_if(!duplicated(str_remove(names(.), '\..*')))