Pur*_*mon 13 r duplicates dataframe dplyr
这是一个示例数据框,用于显示我的问题和我想要实现的目标。这里我有两列x
和y
,我想从中删除重复项。我还有z
包含行的排序排名的列。
x y z
1 A BB 8
2 B BB 7.5
3 B AA 6.2
4 B CC 5
5 C DD 4
6 D CC 3
Run Code Online (Sandbox Code Playgroud)
我试图同时查看两者,每次两列中都有重复项时,然后删除该行并继续x
。y
我正在寻找的最终结果是
x y z
1 A BB 8
3 B AA 6.2
5 C DD 4
6 D CC 3
Run Code Online (Sandbox Code Playgroud)
BB
列中的第二个y
被删除。然后,该B - AA
行不会被删除,因为逐行向下,它现在是列B
中的第一行x
。这是针对大型数据集的,因此不幸的是我无法手动完成。
我并不是想将这两列组合在一起。我也不想一次删除一列的重复项,因为如果这样做的话,就会删除太多的观察结果。
如何才能实现这一目标?
由于我们需要同时检查两列,我怀疑我们是否可以使用顺序检查 x 和 y 列,duplicated()
因此这是我的报价较慢但可能更可靠:
i <- 2
repeat {
row_removed <- F
if(df[i,]$x %in% df[1:(i-1),"x"]) {
df <- df[-i,]
row_removed <- T
}
if (i>nrow(df)) break
if(df[i,]$y %in% df[1:(i-1),"y"]) {
df <- df[-i,]
row_removed <- T
}
if (!row_removed) i <- i + 1
if (i>nrow(df)) break
}
Run Code Online (Sandbox Code Playgroud)
结果:
x y z
1 A BB 8.0
3 B AA 6.2
5 C DD 4.0
Run Code Online (Sandbox Code Playgroud)
对于编辑后的数据集,它还返回 OP 预期的结果:
x y z
1 A BB 8.0
3 B AA 6.2
5 C DD 4.0
6 D CC 3.0
Run Code Online (Sandbox Code Playgroud)
这解决了我的问题。
remove_top_duplicate <- function(tempdf) {
tempdf <- tempdf %>%
group_by(x) %>%
mutate(xrep = row_number()) %>%
ungroup() %>%
group_by(y) %>%
mutate(yrep = row_number()) %>%
ungroup()
if(!(any(tempdf$xrep > 1)) & !(any(tempdf$yrep > 1))){
break
}
tempdf <- slice(tempdf, -which(xrep > 1 | yrep > 1)[1])
return(tempdf)
}
while(TRUE){
df <- remove_top_duplicate(df)
if(!(any(df$xrep > 1)) & !(any(df$yrep > 1))){
print("Finished")
break
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个函数,它接受日期范围,并 row_numbers()
首先为 x 改变列,然后为 y 改变列。这样我们就有了两列xrep
,yrep
我们可以在其中找到最上面的重复项。然后我只对发现的大于的第一行进行切片,1
然后返回数据帧。因为这是一个函数,所以我只是在某种while(TRUE)
情况下运行它,然后等待直到重复列中没有2's
,此时我们知道不再有重复项。
这是第一次运行后的示例。然后,由于列2
中的 ,它将对第二行进行切片yrep
。之后,它返回数据帧,然后重复重新计算的过程。然后再切片。
x y z xrep yrep
1 A BB 8 1 1
2 B BB 7.5 1 2
3 B AA 6.2 2 1
4 B CC 5 3 1
5 C DD 4 1 1
6 D CC 3 1 2
Run Code Online (Sandbox Code Playgroud)
这不是一个干净的解决方案,但它可以完成工作。