我正在寻找一种更好的方法来在R中执行此操作。我确实有一种可能,但似乎应该有一种智能/可读性更高的方法。
仅当满足另一列(或多列)中的条件时,我才想删除一个/多个列中的重复项。
在我的简化示例中,仅当列X
为Y
时,我才想删除列NA
中的重复项,但将NA
的Y保留为Y,而没有重复的X。
testDF<- data.frame(X= c(1:4,4:8,8:12), Y = 1:14)
testDF$Y[c(4,6,10)]<- NA
我当前的解决方案是:
testDF[!(testDF$X %in% testDF$X[which(duplicated(testDF$X))] & is.na(testDF$Y)),]
或
library(dplyr)
testDF %>%
dplyr::filter(!(testDF$X%in% testDF$X[which(duplicated(testDF$X))] & is.na(testDF$Y)))
看上去既混乱又混乱,在一个实际的应用程序中,我要查看两个以上的列可能会变得不可行。
我希望有更多类似的东西:
testDF %>% dplyr::filter(!(duplicated(X) & is.na(Y)))
但它duplicated()
仅标识重复的第二个实例,因此,如果Y
的{{1}}与重复的X值中的第一个一致,则不会将其滤除
最好寻找基本解决方案或整洁解决方案,因为脚本的其余部分都不使用data.table
答案 0 :(得分:2)
我们可以排列各列,按X
分组,然后按slice
排列第一行。这样,我们可以在Y
中获得非NA行(如果该行存在)。
library(dplyr)
testDF %>%
arrange(X, Y) %>%
group_by(X) %>%
slice(1) %>%
ungroup()
# # A tibble: 12 x 2
# X Y
# <int> <int>
# 1 1 1
# 2 2 2
# 3 3 3
# 4 4 5
# 5 5 NA
# 6 6 7
# 7 7 8
# 8 8 9
# 9 9 11
# 10 10 12
# 11 11 13
# 12 12 14
答案 1 :(得分:2)
您还可以从两个方向同时应用duplicated
:
testDF %>%
filter(!is.na(Y) | (!duplicated(X) & !duplicated(X, fromLast = TRUE) ))
(受此影响很大:Find duplicated elements with dplyr-我会让其他人决定是否足够接近以至于可以重复)
为使代码更具可读性,您甚至可以将其放入函数中(也许比我的函数名更好):
all_duplicates <- function(x) {
duplicated(x) | duplicated(x, fromLast = TRUE)
}
testDF %>%
filter(!is.na(Y) | !all_duplicates(X) )
答案 2 :(得分:0)
我有类似的想法,例如@www建议,先排列X和Y,然后排列filter
而不是slice
。
第一个过滤条件为row_number()==1
,好像row_number == 1
表示X是唯一的。
第二个过滤条件为!is.na(Y)
,它将仅保留Y不是NA的任何X。
testDF %>% arrange(X,Y) %>%
group_by(X) %>% filter(row_number()==1 | !is.na(Y)) %>% ungroup()