我有一个长度为N的数组X,我想计算sum(X[(i+1):N]) - sum(X[1:(i-1)]
。如果我的索引i在2 ..(N-1)之内,则可以正常工作。如果等于1,则第二项将返回数组的第一个元素,而不是排除它。如果等于N,则第一项将返回数组的最后一个元素,而不是排除它。 seq_len是我所知道的唯一可以完成此功能的函数,但仅适用于第二项(索引为1:n)。我需要的是一个范围函数,当它的第二个参数低于第一个参数时,它将返回NULL(而不是抛出类似seq的异常)。 sum函数将完成其余的工作。有谁知道一个,还是我必须自己写一个?
答案 0 :(得分:2)
我建议使用另一种生成索引序列的路径:seq_len
,在极端情况下可以直观地做出反应。
最底线:改为使用sum(X[-seq_len(i)]) - sum(X[seq_len(i-1)])
。
首先,提供一些示例数据:
X <- 1:10
N <- length(X)
您的方法有两个极端:
i <- 1
X[(i+1):N]
# [1] 2 3 4 5 6 7 8 9 10
X[1:(i-1)] # oops
# [1] 1
我相信,应该返回“无”。 (更重要的是,sum(...)
应该返回0。对于记录,sum(integer(0))
是0。)
i <- 10
X[(i+1):N] # oops
# [1] NA 10
X[1:(i-1)]
# [1] 1 2 3 4 5 6 7 8 9
还有另一个错误,您期望第一个子集“什么都没有”。
相反,我建议您使用seq_len
:
i <- 1
X[-seq_len(i)]
# [1] 2 3 4 5 6 7 8 9 10
X[seq_len(i-1)]
# integer(0)
i <- 10
X[-seq_len(i)]
# integer(0)
X[seq_len(i-1)]
# [1] 1 2 3 4 5 6 7 8 9
两者看起来都不错,中间的东西很有意义。
i <- 5
X[-seq_len(i)]
# [1] 6 7 8 9 10
X[seq_len(i-1)]
# [1] 1 2 3 4
在这个人为的示例中,我们要寻找的是i
的任何值:
1: sum(2:10) - 0 = 54 - 0 = 54
2: sum(3:10) - sum(1:1) = 52 - 1 = 51
3: sum(4:10) - sum(1:2) = 49 - 3 = 46
...
10: 0 - sum(1:9) = 0 - 45 = -45
现在我们得到了:
func <- function(i, x) sum(x[-seq_len(i)]) - sum(x[seq_len(i-1)])
sapply(c(1,2,3,10), func, X)
# [1] 54 51 46 -45
修改:
李哲源's answer使我认为您不需要一直重新sum
之前和之后的数字。只需执行一次并重新使用它。如果您的向量很大,此方法可能会更快一点。
Xb <- c(0, cumsum(X)[-N])
Xb
# [1] 0 1 3 6 10 15 21 28 36 45
Xa <- c(rev(cumsum(rev(X)))[-1], 0)
Xa
# [1] 54 52 49 45 40 34 27 19 10 0
sapply(c(1,2,3,10), function(i) Xa[i] - Xb[i])
# [1] 54 51 46 -45
因此,这表明您在i
的任何值处的总和为
Xs <- Xa - Xb
Xs
# [1] 54 51 46 39 30 19 6 -9 -26 -45
,您可以在其中找到Xs[i]
的特定值。无需重复求和。