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

时间:2019-09-27 10:19:46

标签: r dplyr readr

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

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

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

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

但是,如果数据以.xlsx格式存在于工作表中,并且我使用read_excel()包中的readxl函数,则重复的列将导入为:

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

在这种情况下,两列都被重命名,而使用read_csv(),仅多余的实例被重命名。在这种情况下,我必须匹配整个字符串才能删除重复的列。我不知道哪些数字将分配给重复的列。我认为它是基于列索引的?此外,即使使用read_csv()导入,如果我的列在原始数据中的名称中自然都带有下划线,那么我的解决方案将无法使用。所以我的问题是,如何删除tidyverse中带有重复存储的数据的重复列?对于底数为R的duplicated(),这很容易。但这不适用于tidyverse的修改。我知道dplyr动词是按列名而不是按列索引选择的,因此列名始终必须不同。但是,有没有一种方法可以始终使用tidyverse删除重复的列,而无需查看控制台来查看新的重复的名称?

3 个答案:

答案 0 :(得分:2)

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

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"列,并仅选择第一个重复的值。

答案 1 :(得分:2)

以罗纳克(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(.))))

答案 2 :(得分:1)

或者使用select_ifstr_remove

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