Suppose I have the vector
v = 0:12
Is it possible to create a new vector which sums different subsets of that vector v together without using a for loop? For example:
Suppose I wanted to sum the first 1 elements together, then the next 2 elements, then the next 3 elements, then the next 4 elements. Then you would end up with vector:
0 3 12 21 42
Can this be done without a for loop? I am not sure.
CodePudding user response:
You can try by
to make vector values grouped and summed
> n <- ceiling(sqrt(2 * length(v)))
> c(by(v, head(rep(1:n, 1:n), length(v)), sum))
1 2 3 4 5
0 3 12 30 33
CodePudding user response:
> n=4;l=n*(n 1)/2;v=0:(l-1)
> sapply(split(v,rep(1:n,1:n)),sum)
1 2 3 4
0 3 12 30
Or if the length of the vector is not n*(n 1)/2
:
> v=0:12
> l=length(v)
> n=ceiling((sqrt(8*l 1)-1)/2)
> r=head(rep(1:n,1:n),l)
> sapply(split(v,r),sum)
1 2 3 4 5
0 3 12 30 33
> tapply(v,r,sum)
1 2 3 4 5
0 3 12 30 33
The second argument for tapply
is automatically converted to a factor:
tapply package:base R Documentation
Apply a Function Over a Ragged Array
Description:
Apply a function to each cell of a ragged array, that is to each
(non-empty) group of values given by a unique combination of the
levels of certain factors.
Usage:
tapply(X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)
Arguments:
X: an R object for which a split method exists. Typically
vector-like, allowing subsetting with [.
INDEX: a list of one or more factors, each of same length as
‘X’. The elements are coerced to factors by as.factor.
I derived the value of n
by using the quadratic formula:
l=n*(n-1)/2
2*l=n^2 n
n^2 n-2*l=0
n=(-1±sqrt(1^2-4*1*-2*l))/2*1
n=(-1±sqrt(1 8*l))/2
n*(n-1)/2
is the same as sum(1:(n-1))
and choose(n,2)
and length(which(lower.tri(matrix(,n,n))))
.