【问题标题】:Remove duplicated rows删除重复的行
【发布时间】:2012-12-07 16:07:09
【问题描述】:

我已将 CSV 文件读入 R data.frame。一些行在其中一列中具有相同的元素。我想删除该列中重复的行。例如:

platform_external_dbus          202           16                     google        1
platform_external_dbus          202           16         space-ghost.verbum        1
platform_external_dbus          202           16                  localhost        1
platform_external_dbus          202           16          users.sourceforge        8
platform_external_dbus          202           16                    hughsie        1

我只想要这些行中的一个,因为其他行在第一列中具有相同的数据。

【问题讨论】:

  • 你想要哪一个?只是第一个?换句话说:您要保留googlelocalhosthughsie 吗?
  • 这部分我的统计分析没关系。我只是想将项目标题(第一列)、错误数量(第二列)和项目中的组织数量(第三列)联系起来。
  • 酷。扔掉不必要的列并使用 ?unique

标签: r duplicates r-faq


【解决方案1】:

对于来这里寻找删除重复行的一般答案的人,请使用!duplicated()

a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

duplicated(df)
[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE

> df[duplicated(df), ]
  a b
2 A 1
6 B 1
8 C 2

> df[!duplicated(df), ]
  a b
1 A 1
3 A 2
4 B 4
5 B 1
7 C 2

答案来自:Removing duplicated rows from R data frame

【讨论】:

  • 我想创建一个新的变量来标记是否存在重复的某个变量几乎就像 df$duplicates
  • @jacob 看到这个问题stackoverflow.com/questions/12495345/…
  • 这会保留第一个出现的值并删除其余的重复值,对吗?还是随机删除值?
  • @alphabetagamma 是的,它保留了第一个出现的值
  • 如果您只对某些列中的重复项感兴趣,例如列 1 和列 2,我们可以使用 df[!duplicated(df[, 1:2])]
【解决方案2】:

只需将您的数据框隔离到您需要的列,然后使用独特的功能:D

# in the above example, you only need the first three columns
deduped.data <- unique( yourdata[ , 1:3 ] )
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out.

【讨论】:

  • 这看起来可以完美运行。您能否向我解释一下该代码的[,1:3] 部分发生了什么?我是 R 新手,这就是为什么我要问我只能假设是一个明显的问题。
  • @user1897691 将其标记为正确 ;) watch this 如果你喜欢,请检查twotorials.com
  • 请注意,这将删除除前三个列之外的所有列。
【解决方案3】:

dplyr 包中的函数 distinct() 执行任意重复删除,无论是从特定列/变量(如本问题中)还是考虑所有列/变量。 dplyrtidyverse 的一部分。

数据和包

library(dplyr)
dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2))

删除特定列中重复的行(例如,columna

注意.keep_all = TRUE 会保留所有列,否则只会保留a 列。

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

删除与其他行完全重复的行:

distinct(dat)

  a b
1 1 A
2 2 B
3 1 C
4 2 D

【讨论】:

  • 很好的答案,顺便说一句,.keep_all 用于是否保留所有列,不要与pandas 中的keep 混合。
【解决方案4】:

data.table 包还具有自己的 uniqueduplicated 方法以及一些附加功能。

unique.data.tableduplicated.data.table 方法都有一个额外的 by 参数,允许您分别传递列名或其位置的 characterinteger 向量

library(data.table)
DT <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

unique(DT, by = "id")
#    id val
# 1:  1  10
# 2:  2  10

duplicated(DT, by = "id")
# [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

这些方法的另一个重要特点是对更大的数据集有巨大的性能提升

library(microbenchmark)
library(data.table)
set.seed(123)
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10))
DT <- copy(DF)
setDT(DT)

microbenchmark(unique(DF), unique(DT))
# Unit: microseconds
#       expr       min         lq      mean    median        uq       max neval cld
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18   100   b
# unique(DT)   746.855   776.6145  2201.657   864.932   919.489  55986.88   100  a 


microbenchmark(duplicated(DF), duplicated(DT))
# Unit: microseconds
#           expr       min         lq       mean     median        uq        max neval cld
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170   100   b
# duplicated(DT)   551.982   558.2215   851.0246   639.9795   663.658   5805.243   100  a 

【讨论】:

    【解决方案5】:

    一般的答案可以是 例如:

    df <-  data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6))))
    
    
    
    new_df <- df[-which(duplicated(df)), ]
    

    输出:

          X1 X2 X3
        1  2  9  6
        2  4  6  7
    

    【讨论】:

    • 使用-which时要小心,如果没有重复会导致错误,使用df[!(duplicated(df)), ]可能会更安全。
    【解决方案6】:

    你也可以使用dplyrdistinct()函数!它往往比其他选项更有效,尤其是在您有大量观察结果的情况下。

    distinct_data <- dplyr::distinct(yourdata)
    

    【讨论】:

    • 这与 Sam Firke 的答案相同,但细节较少。
    【解决方案7】:

    sqldf:

    # Example by Mehdi Nellen
    a <- c(rep("A", 3), rep("B", 3), rep("C",2))
    b <- c(1,1,2,4,1,1,2,2)
    df <-data.frame(a,b)
    

    解决方案:

     library(sqldf)
        sqldf('SELECT DISTINCT * FROM df')
    

    输出:

      a b
    1 A 1
    2 A 2
    3 B 4
    4 B 1
    5 C 2
    

    【讨论】:

    • 这会产生设置整个 SQL 数据库的开销。 cran.r-project.org/web/packages/sqldf/index.html
    • 建立一个完整的 SQL 数据库是什么意思?这是主要优点之一:'使用 sqldf,用户不必执行以下操作,所有这些都是自动完成的:数据库设置,编写定义每个表的创建表语句,导入和导出数据库'。这不是最佳解决方案,但对于熟悉 SQL 的人来说很方便。
    【解决方案8】:

    这里有一个非常简单快速的dplyr/tidy解决方案:

    删除完全相同的行:

    library(dplyr)
    iris %>% 
      distinct(.keep_all = TRUE)
    

    删除仅在某些列中相同的行:

    iris %>% 
      distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
    
    

    【讨论】:

      【解决方案9】:

      或者您可以使用tidyr 将第 4 列和第 5 列中的数据嵌套到一行中:

      library(tidyr)
      df %>% nest(V4:V5)
      
      # A tibble: 1 × 4
      #                      V1    V2    V3             data
      #                  <fctr> <int> <int>           <list>
      #1 platform_external_dbus   202    16 <tibble [5 × 2]>
      

      现在删除了第 2 列和第 3 列的重复数据以进行统计分析,但您已将第 4 列和第 5 列数据保留在一个小标题中,并且可以随时使用unnest() 返回原始数据框。

      【讨论】:

        【解决方案10】:

        删除数据框的重复行

        library(dplyr)
        mydata <- mtcars
        
        # Remove duplicate rows of the dataframe
        distinct(mydata)
        

        在这个数据集中,没有一个重复的行,因此它返回的行数与 mydata 中的相同。



        根据一个变量删除重复行

        library(dplyr)
        mydata <- mtcars
        
        # Remove duplicate rows of the dataframe using carb variable
        distinct(mydata,carb, .keep_all= TRUE)
        

        .keep_all 函数用于保留输出数据框中的所有其他变量。



        根据多个变量删除重复行

        library(dplyr)
        mydata <- mtcars
        
        # Remove duplicate rows of the dataframe using cyl and vs variables
        distinct(mydata, cyl,vs, .keep_all= TRUE)
        

        .keep_all 函数用于保留输出数据框中的所有其他变量。

        (来自:http://www.datasciencemadesimple.com/remove-duplicate-rows-r-using-dplyr-distinct-function/

        【讨论】:

          【解决方案11】:

          这个问题也可以通过从每个组中选择第一行来解决,其中组是我们想要选择唯一值的列(在共享的示例中它只是第一列)。

          使用基础 R:

          subset(df, ave(V2, V1, FUN = seq_along) == 1)
          
          #                      V1  V2 V3     V4 V5
          #1 platform_external_dbus 202 16 google  1
          

          dplyr

          library(dplyr)
          df %>% group_by(V1) %>% slice(1L)
          

          或者使用data.table

          library(data.table)
          setDT(df)[, .SD[1L], by = V1]
          

          如果我们需要根据多列找出唯一行,只需将这些列名添加到上述每个答案的分组部分即可。

          数据

          df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
          .Label = "platform_external_dbus", class = "factor"), 
          V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
          16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
          "hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
          ), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
          row.names = c(NA, -5L))
          

          【讨论】:

            猜你喜欢
            • 2018-04-07
            • 2015-01-19
            • 2011-04-16
            • 2012-05-31
            相关资源
            最近更新 更多