在向量(R)中的某些值上应用函数

qee*_*eZz 5 r vector

我想知道这个问题是否有一些优雅的解决方案:

假设我有一个值向量

a <- c(1,2,3,3.1,3.2,5,6,7,7.1,7.2,9)

并且我想将一些函数(例如,均值)仅应用于满足特定条件的值,在这种情况下,这些值具有小于0.5的值之间的差值.

所以应该平均的值是(3,3.1,3.2)(7,7.1,7.2)函数应该返回向量

b <- c(1,2,3.1,5,6,7.1,9)

编辑:我尝试过的一种方法(不确定是否正确)是将矢量二a值化(1意味着值之间的差异<0.5; 0意味着差异> 0.5),所以我得到了矢量

bin <– c(0,0,1,1,0,0,0,1,1,0)

但我不知道如何将平均值应用于不同的组.所以我的主要问题是区分所需的值组并分别对它们应用均值.有任何想法吗?

我是新来的,所以如果有什么不清楚的地方,请告诉我.先感谢您.

Ric*_*ron 4

这并不优雅,但我认为它适用于您提供的情况。我使用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))
Run Code Online (Sandbox Code Playgroud)

产量:

> 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
Run Code Online (Sandbox Code Playgroud)

也许有人可以从中构建一个更清洁的解决方案。


更新: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)))
Run Code Online (Sandbox Code Playgroud)

现在,每当遇到小差异运行(即val == TRUE)时,它都会在该小差异运行(即 )的长度上添加更多一个len + val,但是该附加元素来自下一次运行,但它不能从上一次运行中窃取如果差异不小,则运行(即last * !val)。