使用 rollapply 从向量中有条件地提取
Conditional extract from vector using rollapply
我正在尝试从满足特定条件的向量中提取一系列值。为了说明这一点,想象一下我有以下向量:
a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)
我想隔离总和小于 10 的连续值,以便输出如下所示:
[1] 1 2 1 3
[1] 3 2
[1] 1 1 1 1 4
[1] 5
我可以通过使用 zoo::rollsum() 和逻辑测试
非常低效地解决这个问题
which(rollsum(a,2) < 10)
但为了做到这一点,我必须 运行 多次,每次都增加滚动 window。同样,我可以循环执行此操作,但这显然不是最好的方法。
有人能想出解决办法吗?任何帮助将不胜感激!
以下使用 %/%
对累计和进行计算:
idx <- as.numeric(factor(cumsum(a) %/% 10))
ret <- split(a, idx)
ret <- ret[sapply(ret, function(x) all(x < 10))]
ret;
#$`1`
#[1] 1 2 1 3
#
#$`3`
#[1] 3 2
#
#$`5`
#[1] 1 1 1 1 4
#
#$`6`
#[1] 5
解释:as.numeric(factor(...))
returns split
的索引;在最后一步中,我删除了条目 >=10
。
请注意,这是假设 OP 的示例中存在错误,数字 4 似乎重复了。如果OP的示例实际上是正确的,那么我不明白这个问题。
我会使用自己的循环。结果与 Maurits 相同:
a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)
my.roll <- function(x, limit) {
res <- vector("list", length(x))
ctr <- 1
for (i in seq_along(x)) {
res[[ctr]] <- c(res[[ctr]], x[i])
if (sum(res[[ctr]], x[i+1], na.rm = TRUE) > limit) {ctr = ctr+1} else {ctr}
}
res <- res[!sapply(res, is.null) & sapply(res, function(x) sum(x) <= limit)]
return(res)
}
my.roll(a, 10)
我正在尝试从满足特定条件的向量中提取一系列值。为了说明这一点,想象一下我有以下向量:
a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)
我想隔离总和小于 10 的连续值,以便输出如下所示:
[1] 1 2 1 3
[1] 3 2
[1] 1 1 1 1 4
[1] 5
我可以通过使用 zoo::rollsum() 和逻辑测试
非常低效地解决这个问题which(rollsum(a,2) < 10)
但为了做到这一点,我必须 运行 多次,每次都增加滚动 window。同样,我可以循环执行此操作,但这显然不是最好的方法。
有人能想出解决办法吗?任何帮助将不胜感激!
以下使用 %/%
对累计和进行计算:
idx <- as.numeric(factor(cumsum(a) %/% 10))
ret <- split(a, idx)
ret <- ret[sapply(ret, function(x) all(x < 10))]
ret;
#$`1`
#[1] 1 2 1 3
#
#$`3`
#[1] 3 2
#
#$`5`
#[1] 1 1 1 1 4
#
#$`6`
#[1] 5
解释:as.numeric(factor(...))
returns split
的索引;在最后一步中,我删除了条目 >=10
。
请注意,这是假设 OP 的示例中存在错误,数字 4 似乎重复了。如果OP的示例实际上是正确的,那么我不明白这个问题。
我会使用自己的循环。结果与 Maurits 相同:
a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)
my.roll <- function(x, limit) {
res <- vector("list", length(x))
ctr <- 1
for (i in seq_along(x)) {
res[[ctr]] <- c(res[[ctr]], x[i])
if (sum(res[[ctr]], x[i+1], na.rm = TRUE) > limit) {ctr = ctr+1} else {ctr}
}
res <- res[!sapply(res, is.null) & sapply(res, function(x) sum(x) <= limit)]
return(res)
}
my.roll(a, 10)