Векторизация rep и seq в R - PullRequest
4 голосов
/ 21 февраля 2011

Я пытаюсь сделать две вещи. Во-первых, если у меня есть вектор 1:5, я хочу получить матрицу (или два вектора), указывающую уникальные комбинации этих элементов, включающие дважды одинаковое число, но исключая повторы.

Прямо сейчас я могу сделать это, используя матрицу:

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

Но должен быть более простой способ. Я пытался использовать Vectorize на seq, но это выдает ошибку:

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

Второе, что я хочу сделать, - это если у меня есть список, содержащий векторы, bar, чтобы получить вектор, содержащий повторяющиеся элементы списка, равные количеству элементов в этом элементе. Я могу сделать это с:

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

Но опять же, должен быть более легкий путь. Я попытался Vectorize снова здесь, но с той же ошибкой:

Vectorize(rep,"each")(1:length(bar),each=sapply(bar,length))
 in Vectorize(rep, "each") : 
  must specify formal argument names to vectorize

Ответы [ 3 ]

5 голосов
/ 21 февраля 2011

На ваш первый вопрос: как насчет простой функции combn() в базе:

> 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

Если вам нужна матрица, подобранная вами, просто транспонируйте ее с помощью t(), например t(combn(1:5,2))

Примечание: это не вернет вам комбинации повторяющихся элементов вашего seq, но вы можете легко добавить их в матрицу.

5 голосов
/ 21 февраля 2011
> 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

и

> 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
4 голосов
/ 21 февраля 2011

Более быстрый вариант решения Мартина Моргана к первой части:

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

Примерно в 7 и 3 раза быстрее соответственно.

Я не уверен, что понимаю, что вы имеете в виду ввторая часть, но следующее, кажется, соответствует вашему описанию:

lapply(bar,function(x) rep(x,length(x)))
...