如果您有这样的数据框:
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中有一个包可以在不使用函数的情况下执行此操作。
答案 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个向量lenghts
和values
组成的列表:
unclass(rv)
## $lengths
## [1] 2 2 2 2 1 6 1
##
## $values
## [1] 1 5 2 6 1 2 3
我们可以从中创建结果。第一个值1
在输入向量中出现2
次。因此,在输出中,我们需要1
和2-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
答案 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)