R 从数据帧中成对删除重复项
这似乎是一个简单的问题,但我似乎无法解决。如果两列具有相同的值,我希望从数据帧(df)中删除重复项,即使这些值的顺序与相反。我的意思是,假设您有以下数据帧:R 从数据帧中成对删除重复项,r,dataframe,duplicates,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
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
但是,我还想删除此数据框中的第6行,因为“A”、“B”与“B”、“A”相同。我怎样才能自动完成这项工作
理想情况下,我可以指定比较哪两列,因为数据帧可能有不同的列,并且可能相当大
谢谢 一种解决方案是首先对
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
正如注释中提到的最近一封邮件,您的代码实际上保留了副本。您需要使用!复制
以删除它们。扩展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
a其他答案使用for
循环为每一行分配一个值。虽然如果您有100行,甚至1000行,这不是问题,但是如果您有大约1M行的大数据,则需要等待一段时间
使用data.table
从中窃取数据,您可以尝试以下操作:
df[!duplicated(data.frame(list(do.call(pmin,df),do.call(pmax,df)))),]
具有较大数据集的比较基准(df2
):
df2使用apply
将是比循环更好的选择
newDf <- data.frame(t(apply(df,1,sort)))
newDf几乎是重复的-唯一的区别是,如果您出于某种原因想留在data.frame
(不太可能,尤其是当您说您的数据很大,但谁知道呢)您没有用当前代码删除重复项,你在保留重复项。我所说的删除重复项的意思是在两列中保留一个重复模式的单一匹配项,这就是我实际上正在做的。Ari,你在与R相关的问题上帮了大忙。谢谢你的帮助!OP说,“理想情况下,我可以指定要比较的两列,因为数据帧可以有不同的列,并且可以相当大。”我不认为在这个解决方案中可以解决这个问题。这是解决OPApply完整请求的唯一答案,这是一个很好的实用程序。但我认为,如果有两个以上的相关列需要维护,则需要修改此代码。
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
newDf <- data.frame(t(apply(df,1,sort)))
newDf <- newDf[!duplicated(newDf),]