这不符合优雅的条件,但我认为它适用于您提供的情况。我使用rle (base R) 来识别差异小于 0.5 的运行。
a <- c(1, 2, 3, 3.1, 3.2, 5, 6, 7, 7.1, 7.2, 9)
crit <- diff(a) < 0.5
crit <- c(head(crit, 1), crit) | c(crit, tail(crit, 1))
run <- rle(crit)
aa <- split(a, rep(seq(length(run$lengths)), times=run$lengths))
myFun <- function(crit, val) {
if (crit) {
mean(val)
}
else {
val
}
}
unlist(mapply(FUN=myFun, crit=run$values, val=aa, USE.NAMES=FALSE))
产量:
> unlist(mapply(FUN=myFun, crit=run$values, val=aa, USE.NAMES=FALSE))
[1] 1.0 2.0 3.1 5.0 6.0 7.1 9.0
也许有人可以从中构建更清洁的解决方案。
更新:OP 指出这在 {3, 3.1, 3.2, 7, 7.1, 7.2} 之类的序列上失败,因为上面的代码将其集中在一次运行中并在整个序列中取平均值。这是一个更强大的解决方案。
a <- c(1, 2, 3, 3.1, 3.2, 7, 7.1, 7.2, 10)
run <- unclass(rle(diff(a) < 0.5))
len <- run$lengths
val <- run$values
pos <- seq_along(len)
last <- pos == max(pos)
len <- len + val - c(0, head(val, -1)) + (last * !val)
prevLen <- c(0, head(cumsum(len), -1))
myFun <- function(l, v, pl, x) {
if (l == 0) {
NULL
} else {
seg <- seq(l) + pl
if (v == TRUE) {
mean(x[seg])
} else {
x[seg]
}
}
}
unlist(mapply(FUN=myFun, l=len, v=val, pl=prevLen, MoreArgs=list(x=a)))
现在,每当遇到小差异运行(即val == TRUE)时,它都会在该小差异运行的长度上增加一个(即len + val),但该附加元素来自下一次运行,但是如果它不是一个小的差异运行(即last * !val),它不能从上次运行中窃取。