Vectorizing rep and seq in R
I am trying to accomplish two things. First if I have a vector 1:5
I want to get a matrix (or two vectors) indicating the unique combinations of these elements including twice the same number but excluding repetitions.
Right now I can do this using a matrix:
foo <- matrix(1:5,5,5)
cbind(foo[upper.tri(foo,diag=TRUE)],foo[lower.tri(foo,diag=TRUE)])
[,1] [,2]
[1,] 1 1
[2,] 1 2
[3,] 2 3
[4,] 1 4
[5,] 2 5
[6,] 3 2
[7,] 1 3
[8,] 2 4
[9,] 3 5
[10,] 4 3
[11,] 1 4
[12,] 2 5
[13,] 3 4
[14,] 4 5
[15,] 5 5
But there has to be a simpler way. I tried to use Vectorize
on seq
but this gives me an error:
cbind(Vectorize(seq,"from")(1:5,5),Vectorize(seq,"to")(5,1:5))
Error in Vectorize(seq, "from") :
must specify formal argument names to vectorize
A second thing I want to do is if I have a list containing vectors, bar
, to get a vector containing the elements of the list repeated equal to the number of elements in that element. I can do this with:
unlist(apply(rbind(1:length(bar),sapply(bar,length)),2,function(x)rep(x[1],x[2])))
[1] 1 1 1 1 1 2 2 2 2 2 2 2 3开发者_如何学JAVA 3 3 3 3 3 3 3 3 3
But again there must be an easier way. I tried Vectorize
again here but with the same error:
Vectorize(rep,"each")(1:length(bar),each=sapply(bar,length))
in Vectorize(rep, "each") :
must specify formal argument names to vectorize
To your first question: what about the simple combn()
function in base:
> combn(1:5,2)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 1 1 2 2 2 3 3 4
[2,] 2 3 4 5 3 4 5 4 5 5
If you need a matrix arranged the one you made up, just transpose it with t()
, like t(combn(1:5,2))
Note: this will not give you back the combinations of repeated elements of your seq, but you may add those easily to the matrix.
> unlist(lapply(1:5, seq, from=1))
[1] 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
> unlist(lapply(1:5, seq, 5))
[1] 1 2 3 4 5 2 3 4 5 3 4 5 4 5 5
and
> bar = lapply(1:5, seq, from=1)
> rep(seq_along(bar), sapply(bar, length))
[1] 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
A faster variation of Martin Morgan's solution to the first part:
rep(1:5,5:1)
[1] 1 1 1 1 1 2 2 2 2 3 3 3 4 4 5
unlist(lapply(1:5,function(x) x:5))
[1] 1 2 3 4 5 2 3 4 5 3 4 5 4 5 5
Roughly 7 and 3 times faster respectively.
I'm not sure I follow what you mean in the second part, but the following seems to fit your description:
lapply(bar,function(x) rep(x,length(x)))
精彩评论