基于向量的下一个值的条件 cumsum
Conditional cumsum based on the next value of a vector
我正在尝试根据以下条件计算具有元素 0,1,NA 的向量的累积和:
1) 只需计算 NA 值之间的累积和
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 值之间的累积和:
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
现在我遇到的问题是,如果 1 后跟一个零(这里只是第一个零),我想得到 cumsum+1
例如
0 1 1 0 0 0 1 0 1 1 不适用
用我现在拥有的功能我会得到
0 1 2 2 2 2 3 3 4 5 NA,但我想要的是:
0 1 2 3 3 3 4 5 6 7 不适用
有人可以帮忙吗?谢谢。
应该有更简单的方法,但你可以试试这个:
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
试试这个
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
),然后 "add" 通过识别需要添加的序列 [=] 缺少的位
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]
我正在尝试根据以下条件计算具有元素 0,1,NA 的向量的累积和:
1) 只需计算 NA 值之间的累积和
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 值之间的累积和:
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
现在我遇到的问题是,如果 1 后跟一个零(这里只是第一个零),我想得到 cumsum+1
例如
0 1 1 0 0 0 1 0 1 1 不适用
用我现在拥有的功能我会得到
0 1 2 2 2 2 3 3 4 5 NA,但我想要的是:
0 1 2 3 3 3 4 5 6 7 不适用
有人可以帮忙吗?谢谢。
应该有更简单的方法,但你可以试试这个:
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
试试这个
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
),然后 "add" 通过识别需要添加的序列 [=] 缺少的位
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]