Vectorizing rep and seq in R

孤者浪人 提交于 2020-01-14 12:59:30

问题


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

回答1:


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.




回答2:


> 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



回答3:


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)))


来源:https://stackoverflow.com/questions/5060850/vectorizing-rep-and-seq-in-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!