与NA擦除重复值

问题描述:

我有这样一个数据帧:与NA擦除重复值

names <- c('Mike','Mike','Mike','John','John','John','David','David','David','David') 
dates <- c('04-26','04-26','04-27','04-28','04-27','04-26','04-01','04-02','04-02','04-03') 
values <- c(NA,1,2,4,5,6,1,2,NA,NA) 
test <- data.frame(names,dates,values) 

那就是:

names dates values 
1 Mike 04-26  NA 
2 Mike 04-26  1 
3 Mike 04-27  2 
4 John 04-28  4 
5 John 04-27  5 
6 John 04-26  6 
7 David 04-01  1 
8 David 04-02  2 
9 David 04-02  NA 
10 David 04-03 NA 

我想获得与NA值去掉重复的。因此,在这种情况下,我在04-26从迈克得到了一个有效的观察结果,并且在04-02上也得到了来自David的有效观察结果,因此第1行和第9行应该被擦除,并且我将以:

 names dates values 
1 Mike 04-26  1 
2 Mike 04-27  2 
3 John 04-28  4 
4 John 04-27  5 
5 John 04-26  6 
6 David 04-01  1 
7 David 04-02  2 
8 David 04-03  NA 

我试图用duplicated功能,这样的事情:

test[!duplicated(test[,c('names','dates')]),] 

但是,这并不工作,因为一些NA值之前的有效值来。如果没有尝试诸如merge之类的东西或制作其他数据框,您是否有任何建议?

更新:我想保留与NA不重复的行。

+0

如果有'NA'但没有重复怎么办? – DatamineR

+0

我希望保持NA值不重复 – ahoosh

这里是data.table企图:

# set up 
libary(data.table) 
setDT(test) 

# construct condition 
test[, dupes := max(duplicated(.SD)), .SDcols=c("names", "dates"), by=c("names", "dates")] 

# print out result 
test[dupes == 0 | !is.na(values),] 

这里是一个类似的方法,使用碱R,所不同的是易受骗变量是从data.frame分开保存:

dupes <- duplicated(test[c("names", "dates")]) 
# this generates warnings, but works nonetheless 
dupes <- ave(dupes, test$names, test$dates, FUN=max) 
# print out result 
test[dupes == 0 | !is.na(test$values),] 

如果有重复行的值变量为NA,并且这些重复值不会向数据添加任何内容,则可以在运行上面的代码之前删除它们:

testNoNADupes <- test[!(duplicated(test) & is.na(test$values)),] 
+0

非常感谢。这正是我正在寻找的。尽管如此,对于我拥有的大型数据集(200万行)来说,它有点慢。 – ahoosh

+0

@Imo如果还有另一行“David 04-03 NA”,我们想保留“David 04-03 NA”?因为不是这些行是NA和dupes,所以'David 04-03 NA'将被删除。但是,我们想保留它。 – ahoosh

+1

@bikhaab查看完成此操作的一种方法的最后一行代码。 – lmo

这种方式怎么样?

library(dplyr) 
test %>% group_by(names, dates) %>% filter((n()>=2 & !is.na(values)) | n()==1) 
Source: local data frame [8 x 3] 
Groups: names, dates [8] 

    names dates values 
    (fctr) (fctr) (dbl) 
1 Mike 04-26  1 
2 Mike 04-27  2 
3 John 04-28  4 
4 John 04-27  5 
5 John 04-26  6 
6 David 04-01  1 
7 David 04-02  2 
8 David 04-03  NA 
+0

或受[tag:slice]标签启发:'test%>%arrange(values)%>%group_by(names,dates)%>%slice( 1L)“,因为当你”安排“时,”NA“就会结束。 – Frank

+0

这很好。如果列名不会改变,那将会很棒。 – ahoosh

+0

@bikhaab他们实际上并没有改变,他们只是打印这种方式,但列名保持不变 – DatamineR

这应该基于您的示例工作。

test <- test[order(test$values),] 
test <- test[!(duplicated(test$names) & duplicated(test$dates) & is.na(test$values)),] 
+0

我不喜欢改变行的顺序。此外,这只是一个例子,解决方案不适用于一般情况。 – ahoosh

+0

'test