根据另一列删除一列中的重复项

时间:2018-06-22 01:19:29

标签: r filter dplyr duplicates

我正在寻找一种更好的方法来在R中执行此操作。我确实有一种可能,但似乎应该有一种智能/可读性更高的方法。

仅当满足另一列(或多列)中的条件时,我才想删除一个/多个列中的重复项。

在我的简化示例中,仅当列XY时,我才想删除列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

3 个答案:

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