【问题标题】:Erasing duplicates with NA values删除具有 NA 值的重复项
【发布时间】:2016-08-23 17:10:48
【问题描述】:

我有一个这样的数据框:

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 有来自 Mike 的有效观察,并且在 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 不重复的行。

【问题讨论】:

  • 如果有NA但没有重复怎么办?
  • 我想保留NA 的值,不要重复

标签: r duplicates slice


【解决方案1】:

这是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),]

这里是使用base R的类似方法,除了dupes变量与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)),]

【讨论】:

  • 太好了,谢谢。这正是我想要的。不过,对于我拥有的大型数据集(200 万行),它有点慢。
  • @Imo 如果有另一行 David 04-03 NA 而我们想保留 David 04-03 NA 怎么办?因为这些行都不是 NA 和欺骗,David 04-03 NA 将被删除。但是,我们想保留它。
  • @bikhaab 查看最后一行代码,了解实现此目的的一种方法。
【解决方案2】:

这应该根据您的示例起作用。

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

【讨论】:

  • 我不喜欢更改行的顺序。此外,这只是一个示例,该解决方案不适用于一般情况。
  • test &lt;- test[sample(nrow(test), 2000000, replace=T)。这仍然对我有用。如果您不考虑修改您的问题。
【解决方案3】:

这样怎么样?

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

【讨论】:

  • 或者,受slice 标签的启发:test %&gt;% arrange(values) %&gt;% group_by(names, dates) %&gt;% slice(1L),因为当您arrange 时,NAs 就结束了。
  • 这很好用。如果列名不会改变,那就太好了。
  • @bikhaab 它们实际上并没有改变,它们只是以这种方式打印,但列名保持不变
猜你喜欢
  • 2014-11-13
  • 2022-06-13
  • 1970-01-01
  • 2018-10-21
  • 2011-09-02
  • 2021-05-28
  • 2017-01-17
  • 1970-01-01
  • 2019-11-14
相关资源
最近更新 更多