[英]Conditional cumsum based on the next value of a vector
我正在嘗試根據以下條件計算具有元素0,1,NA的向量的累積和:
1)只需計算NA值之間的cumsums
2)如果0在1之后,那么我想要cumsum + 1
Out是原始向量:
out[1:100]
[1] NA NA NA NA 0 1 1 NA NA NA 1 NA 0 NA 0 1 NA NA 0 NA 0 1 0 0 0 NA 0 1 0 1 0 0 1 0 1 1 0 0 0 0
[41] 1 0 NA 0 0 NA 1 NA 0 1 NA 0 NA 0 1 1 NA 1 NA 0 0 0 1 1 NA NA NA 0 0 NA 0 0 0 1 0 NA 1 0 NA 0
[81] 1 1 0 1 1 0 1 0 NA 0 1 0 1 0 NA 0 1 0 0 1
我使用此代碼計算NA值之間的cumsums:
g <- cumsum(is.na(head(c(0, out), -1)))
out1 <- ave(out, g, FUN = cumsum)
我明白了
out1[1:100]
[1] NA NA NA NA 0 1 2 NA NA NA 1 NA 0 NA 0 1 NA NA 0 NA 0 1 1 1 1 NA 0 1 1 2 2 2 3 3 4 5 5 5 5 5
[41] 6 6 NA 0 0 NA 1 NA 0 1 NA 0 NA 0 1 2 NA 1 NA 0 0 0 1 2 NA NA NA 0 0 NA 0 0 0 1 1 NA 1 1 NA 0
[81] 1 2 2 3 4 4 5 5 NA 0 1 1 2 2 NA 0 1 1 1 2
現在我只是有一個問題,我想得到cumsum + 1,如果1后跟一個零(這里只是第一個零)
例如
0 1 1 0 0 0 1 0 1 1 NA
憑借我現在擁有的功能,我會得到
0 1 2 2 2 2 3 3 4 5 NA,但我想要的是:
0 1 2 3 3 3 4 5 6 7 NA
有人可以幫忙嗎? 謝謝。
嘗試這個
out <- c(NA, NA, NA, NA, 0, 1, 1, NA, NA, NA, 1, NA, 0, NA, 0, 1, NA,
NA, 0, NA, 0, 1, 0, 0, 0, NA, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0,
0, 0, 0, 1, 0, NA, 0, 0, NA, 1, NA, 0, 1, NA, 0, NA, 0, 1, 1,
NA, 1, NA, 0, 0, 0, 1, 1, NA, NA, NA, 0, 0, NA, 0, 0, 0, 1, 0,
NA, 1, 0, NA, 0, 1, 1, 0, 1, 1, 0, 1, 0, NA, 0, 1, 0, 1, 0, NA,
0, 1, 0, 0, 1, NA, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, NA)
as.numeric(unlist(lapply(split(out, cumsum(is.na(out))),
function(x) {
if (length(x) == 1) return(x)
idx <- which(x[-length(x)] == 1 & x[-1] == 0)
res <- cumsum(x[-1])
for (i in seq_along(idx)) {
if (i == length(idx))
res[seq(idx[i], length(res))] <- res[seq(idx[i], length(res))] + i
else
res[seq(idx[i], idx[i + 1] - 1)] <- res[seq(idx[i], idx[i + 1] - 1)] + i
}
c(NA, res)
}
)))
# [1] NA NA NA NA 0 1 2 NA NA NA 1 NA 0 NA 0 1 NA NA 0 NA 0 1 2 2 2
# [26] NA 0 1 2 3 4 4 5 6 7 8 9 9 9 9 10 11 NA 0 0 NA 1 NA 0 1
# [51] NA 0 NA 0 1 2 NA 1 NA 0 0 0 1 2 NA NA NA 0 0 NA 0 0 0 1 2
# [76] NA 1 2 NA 0 1 2 3 4 5 6 7 8 NA 0 1 2 3 4 NA 0 1 2 2 3
#[101] NA 0 1 2 3 3 3 4 5 6 7 NA
或者,您可以計算out1
保留現有方法(使用ave
),然后通過識別需要添加的序列來“添加”缺失的位
na.pos <- which(is.na(out))
idx <- which(out[-length(out)] == 1 & out[-1] == 0)
idx2 <- which(is.na(out[-1]) | (out[-length(out)] == 1 & out[-1] == 0))
beg <- idx + 1
end <- idx2[findInterval(idx, idx2) + 1]
to.add <- as.numeric(unlist(sapply(rle(findInterval(idx, na.pos))$lengths, seq, from = 1)))
for(i in seq_along(beg))
out1[seq(beg[i], end[i])] <- out1[seq(beg[i], end[i])] + to.add[i]
應該有一個更簡單的方法,但你可以試試這個:
temp1 <- out
temp1[is.na(temp1)] <- 0
temp2 <- (temp1[2:length(temp1)] == 0) * (temp1[1:length(temp1)-1]==1)
temp2 <- c(0, temp2)
out1 <- cumsum(temp1+temp2)- cummax(cumsum((temp1+temp2))*is.na(out))
out1[is.na(out)] <- NA
rm(temp1, temp2)
out1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.