删除本地重复值

时间:2014-05-23 11:45:32

标签: r

如果您有这样的数据框:

v <- c(1, 1, 5, 5, 2, 2, 6, 6, 1, 2, 2, 2, 2, 2, 2, 3)
w <- data.frame(v)

如何删除w中的重复值并将其替换为NA,仅针对值后面重复的值,以便新数据框看起来像这样?

v <- c(1, NA, 5, NA, 2, NA, 6, NA, 1, 2, NA, NA, NA, NA, NA, 3)
w <- data.frame(v)

请注意2如何连续出现两次并且每次出现时都会保留,并立即重复这些值?

我搜索了SO,我看到使用独特和重复的功能删除每个重复值的响应,但这不是我正在搜索的内容。我希望R中有一个包可以在不使用函数的情况下执行此操作。

4 个答案:

答案 0 :(得分:6)

关键是使用diff()检查差异,并在差异为零时填充NA

> result <- v
> result[c(FALSE,diff(v)==0)] <- NA
> result
 [1]  1 NA  5 NA  2 NA  6 NA  1  2 NA NA NA NA NA  3
> 

答案 1 :(得分:5)

或简单的ifelse

ifelse(lag(v,1) == v & !is.na(lag(v,1)), NA, v)
#[1]  1 NA  5 NA  2 NA  6 NA  1  2 NA NA NA NA NA  3

修改:如果原始向量包含NA,最好使用dplyr::lag而不是stats::lag

答案 2 :(得分:4)

rle是你的朋友:

v <- c(1, 1, 5, 5, 2, 2, 6, 6, 1, 2, 2, 2, 2, 2, 2, 3)
rv <- rle(v)
unlist(sapply(seq_along(rv$lengths), function(i)
   c(rv$values[i], rep(NA, rv$lengths[i]-1))))
## [1]  1 NA  5 NA  2 NA  6 NA  1  2 NA NA NA NA NA  3

说明:rle返回一个由2个向量lenghtsvalues组成的列表:

unclass(rv)
## $lengths
## [1] 2 2 2 2 1 6 1
## 
## $values
## [1] 1 5 2 6 1 2 3

我们可以从中创建结果。第一个值1在输入向量中出现2次。因此,在输出中,我们需要12-1 NA s。然后5出现2次,因此我们得到5, NA,依此类推。

编辑:但是,此解决方案相当慢(比较列出的其他内容):

set.seed(123L)
v <- sample(1:5, 10000, replace=TRUE)
library(microbenchmark)
microbenchmark(...)
## Unit: milliseconds
##                  min         lq     median         uq        max neval
## @Stephan    1.161341   1.193744   1.230734   1.248493   5.867357   100
## @beginneR   2.568235   2.618651   2.655130   3.034742   8.837571   100
## @gagolews 102.307481 111.128368 117.279179 121.308154 195.238260   100

EDIT2 :由于基于rle的基于library(Rcpp) cppFunction(" NumericVector duptrack(NumericVector v) { int n = v.size(); NumericVector out(Rcpp::clone(v)); for (int i=1; i<n; ++i) if (v[i] == v[i-1]) out[i] = NA_REAL; return out; } ") 的解决方案已被接受,这里有一个基于Rcpp的速度爱好者解决方案:

## Unit: milliseconds
##                              min       lq    median       uq     max  neval
## @gagolews-Rcpp          0.077296 0.080160 0.0832595 0.089952 2.31203    100
## @Stephan                1.161027 1.167035 1.1759645 1.223393 6.21994    100

基准:

v <- c(1,1,NA,2,NA,2,2)

EDIT3 :从所有R代码开始,我们也应该对解决方案如何处理缺失值的向量感兴趣。

对于1 NA NA 2 NA 2 NA,我们得到:

  • 1 NA NA 2 NA 2 NA - @gagolews
  • NA NA NA NA NA NA NA - @Stephan
  • stats::lag - @beginneR与1 NA NA 2 NA 2 NA
  • dplyr::lag - @beginneR与1 NA NA 2 NA 2 NA
  • {{1}} - @ gagolews-Rcpp

答案 3 :(得分:0)

你可以这样:

v <- c(1, 1, 5, 5, 2, 2, 6, 6, 1, 2, 2, 2, 2, 2, 2, 3)
x<-c(0,v[1:(length(v)-1)])
v[(v-x)==0]<-'NA'
w<-data.frame(v)