删除重复的行


152

我已经将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

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


3
你想要哪一个?只是第一个?换句话说:您想保留googleor localhost还是hughsie
安东尼·达米科

对于我的统计分析的这一部分都没有关系。我仅试图关联项目标题(第一列),错误数量(第二列)和项目上的组织数量(第三列)。
user1897691 2012年

3
凉。扔掉不必要的列并使用?unique
Anthony Damico

Answers:


186

只需将数据框隔离到所需的列,然后使用独特的功能: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
看起来它将完美地工作。您能告诉我[,1:3]该代码部分的内容吗?我是R的新手,这就是为什么我问我只能假定的一个明显问题。
user1897691 2012年

6
@ user1897691将其标记为正确,然后;) 观看此视频,如果您喜欢,请访问twotorials.com
Anthony Damico

3
请注意,这将删除除前三列之外的所有列。
GuillaumeL

186

对于来这里寻找删除重复行的一般答案的人,请使用!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

答案来自:从R数据框中删除重复的行


我想创建一个新的变量来标记某个变量是否重复就像df $ duplicates <-ifelse(a列中的该行值== a,1,0列中的上一行值)
jacob


2
这样可以保留第一个出现的值,并删除其余重复项,对吗?还是随机删除值?
News_is_Selection_Bias

@alphabetagamma是的,它保留了第一个出现的值
Mehdi Nellen

2
如果您只对某些列中的重复项感兴趣,例如第1列和第2列,则可以使用df[!duplicated(df[, 1:2])]
qwr

82

该功能distinct()dplyr包进行随心所欲重复的去除,或者从特定的列/变量(如在这个问题),或者考虑到所有列/变量。dplyr是的一部分tidyverse

数据和包装

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

删除在特定列(例如column a)中重复的行

请注意,.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是是否保留所有列,而不是与keepin 混合pandas
詹森·目标

28

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 

7

您还可以使用dplyrdistinct()功能!它往往比替代选项更有效,尤其是在您有大量观察数据的情况下。

distinct_data <- dplyr::distinct(yourdata)

1
这与Sam Firke的答案相同,但细节较少。
qwr

6

通用答案可以是例如:

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

1
使用时请小心-which,如果没有重复项,则会导致错误,使用df[!(duplicated(df)), ]可能会更安全。
詹森·目标

5

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
qwr

设置整个SQL数据库是什么意思?这是主要优点之一:'使用sqldf,用户无需执行以下操作,所有这些操作都自动完成:数据库设置,编写定义每个表的create table语句,从数据库导入和导出'。这不是最佳解决方案,但对于熟悉SQL的人来说非常方便。
mpalanco

3

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

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()


1

删除数据框的重复行

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/


0

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

使用基数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))

0

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

删除完全相同的行:

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

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

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.