Простая комбинаторика в R

Я хочу поделиться функцией R для поиска всех возможных уникальных неориентированных комбинаций между элементами одного вектора:

combi <- function(vec1)
{
  si <- length(vec1)
  first <- rep(vec1, (si-1):0)
  secR <- rev(vec1)
  second <- secR[sequence(1:(si-1))]
  second <- rev(second)
  combi <- matrix(cbind(first, second), ncol = 2)
  return(combi)
}

и спросите, есть ли более простой способ сделать это? (Мне нужно, чтобы результат был в матрице из 2 столбцов).

4 ответов


Ну, есть встроенный combn функция:

t(combn(vec1,2))

ваша выглядит быстрее, хотя, возможно, потому, что combn пытается решить более общую проблему (??):

> library(rbenchmark)
> v <- 1:20
> benchmark(combi(v),t(combn(v,2)))
            test replications elapsed relative user.self sys.self
1       combi(v)          100   0.005      1.0     0.004    0.000   
2 t(combn(v, 2))          100   0.044      8.8     0.040    0.004   

существует базовая функция R combn в пакете utils, который, насколько я могу судить, дает идентичные (если перенести) результаты. Разница в том, что combn является более гибким в том смысле, что он также будет вычислять комбинации длины, отличные от 2.

combi(1:5)
      [,1] [,2]
 [1,]    1    2
 [2,]    1    3
 [3,]    1    4
 [4,]    1    5
 [5,]    2    3
 [6,]    2    4
 [7,]    2    5
 [8,]    3    4
 [9,]    3    5
[10,]    4    5

использование базы R 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

вычислить комбинации длины 3:

combn(1:5, 3)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    1    1    1    1    1    2    2    2     3
[2,]    2    2    2    3    3    4    3    3    4     4
[3,]    3    4    5    4    5    5    4    5    5     5

пакета combinat. Отличная куча инструментов для комбинации, перестановки и всего такого.


Спасибо за размещение. Несколько настроек для производительности.

a. Я использовал репутацию.int вместо или rep, при выяснении индексов для первого.

b. Я использовал

second <- secR[rev(sequence(1:(si-1)))]

вместо

second <- secR[sequence(1:(si-1))]
second <- rev(second)

c. Я использовал

matrix(c(first, second), ncol = 2)

вместо

matrix(cbind(first, second), ncol = 2)