library(dplyr)
v <- c(1,1,1,2,2,2,1,1,1,2,1,1,2,2,2,2,2,1,1,1)
这两种解决方案是等价的。他们的问题是忽略了最后一个数字。
v[v != lead(v)] %>% head(-1)
#> [1] 1 2 1 2 1 2
v[v != v[c(2:length(v), NA)]] |> head(-1)
#> [1] 1 2 1 2 1 2
原因是因为最后一个比较是 1 != NA,当我们需要 TRUE 时它返回 NA。如果我们把它改成这样,它就可以工作了:
v[!mapply(identical, v, lead(v))]
#> [1] 1 2 1 2 1 2 1
v[!mapply(identical, v, v[c(2:length(v), NA)])]
#> [1] 1 2 1 2 1 2 1
不过,最简单且可能最快的解决方案是 @Chris 建议的 rle(v)$values。
rle(v)$values
#> [1] 1 2 1 2 1 2 1
library(microbenchmark)
microbenchmark(
v[!mapply(identical, v, lead(v))],
v[!mapply(identical, v, v[c(2:length(v), NA)])],
rle(v)$values
)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> v[!mapply(identical, v, lead(v))] 63.0 65.95 68.308 67.70 69.2 115.5 100
#> v[!mapply(identical, v, v[c(2:length(v), NA)])] 36.7 37.70 38.993 38.20 39.4 65.5 100
#> rle(v)$values 11.1 12.80 14.472 14.45 15.8 32.4 100
由reprex package 创建于 2022-06-10 (v2.0.1)