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

#r #combinatorics

#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 столбцов).

Ответ №1:

Ну, там есть встроенная 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   
  

Комментарии:

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

Ответ №2:

combn В пакете utils есть базовая функция R, которая, насколько я могу судить, дает идентичные (при транспонировании) результаты. Разница в том, что 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
  

Комментарии:

1. Большое спасибо, потому что я был озадачен этой функцией combn.

Ответ №3:

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

Ответ №4:

Спасибо за публикацию. Несколько настроек для повышения производительности.

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

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

 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)