从数据帧中成对重复删除

时间:2014-08-13 23:25:45

标签: r dataframe duplicates

这似乎是一个简单的问题,但我似乎无法弄明白。如果两列具有相同的值,我想从数据框(df)中删除重复项,即使这些值是反向顺序。我的意思是,假设你有以下数据框:

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

  a b
1 A A
2 A B
3 A B
4 B C
5 B A
6 B A
7 C B
8 C B

如果我现在删除重复项,我会得到以下数据框:

df[duplicated(df),]

  a b
3 A B
6 B A
8 C B

但是,我还要删除此数据框中的第6行,因为“A”,“B”与“B”,“A”相同。我该如何自动完成?

理想情况下,我可以指定要比较哪两列,因为数据帧可能具有不同的列,并且可能非常大。

谢谢!

4 个答案:

答案 0 :(得分:6)

扩展Ari的答案,指定列以检查其他列是否也存在:

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

df$c = sample(1:10,8)
df$d = sample(LETTERS,8)
df
  a b  c d
1 A A 10 B
2 A B  8 S
3 A B  7 J
4 B C  3 Q
5 B A  2 I
6 B A  6 U
7 C B  4 L
8 C B  5 V

cols = c(1,2)
newdf = df[,cols]
for (i in 1:nrow(df)){
    newdf[i, ] = sort(df[i,cols])
}

df[!duplicated(newdf),]
  a b c d
1 A A 8 X
2 A B 7 L
4 B C 2 P

答案 1 :(得分:3)

一种解决方案是首先对df的每一行进行排序:

for (i in 1:nrow(df))
{
    df[i, ] = sort(df[i, ])
}
df

a b
1 A A
2 A B
3 A B
4 B C
5 A B
6 A B
7 B C
8 B C

此时只需删除重复的元素:

df = df[!duplicated(df),]
df
  a b 
1 A A
2 A B
4 B C

正如评论中提到的thelatemail,您的代码实际上保留重复项。您需要使用!duplicated删除它们。

答案 2 :(得分:3)

其他答案使用for循环为每一行分配值。如果你有100行甚至上千行,这不是问题,如果你有大约1M行的大数据,你将会等待一段时间。

使用data.tableother linked answer偷窃,您可以尝试以下内容:

df[!duplicated(data.frame(list(do.call(pmin,df),do.call(pmax,df)))),]

具有较大数据集(df2)的比较基准:

df2 <- df[sample(1:nrow(df),50000,replace=TRUE),]

system.time(
  df2[!duplicated(data.frame(list(do.call(pmin,df2),do.call(pmax,df2)))),]
)
# user  system elapsed 
# 0.07    0.00    0.06 

system.time({
  for (i in 1:nrow(df2))
  {
      df2[i, ] = sort(df2[i, ])
  }
  df2[!duplicated(df2),]
}
)
#   user  system elapsed 
#  42.07    0.02   42.09 

答案 3 :(得分:3)

使用apply将是比循环更好的选择。

newDf <- data.frame(t(apply(df,1,sort)))

您现在需要做的就是删除重复项。

newDf <- newDf[!duplicated(newDf),]