Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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
like image 488
Sacha Epskamp Avatar asked Dec 10 '22 10:12

Sacha Epskamp


2 Answers

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.

like image 105
daroczig Avatar answered Jan 01 '23 21:01

daroczig


> 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
like image 30
Martin Morgan Avatar answered Jan 01 '23 23:01

Martin Morgan