Дисперсия функции комбн - PullRequest
0 голосов
/ 07 ноября 2018

Я использовал чудесную функцию combn из пакета utils . Эта функция создает все возможные комбинации без повторений Описание комбинации . Я собираюсь представить одно использование функции, которую мне нужно сделать, но она не определена в функции combn. Я хотел бы представить это с хорошим примером. Тем не менее, реальная цель, которую мы хотим достичь, является более сложной, и она будет выполняться с большим количеством данных.

Мы хотим сыграть в игру, в которую могут играть только 3 человека . Однако мы 4 человека . Мы хотим знать все возможные группы для игры. Имена участников: Алекс , Дэвид , Джон и Зоя . Возможные комбинации:

names <- c("Alex","David","John","Zoe")
people.per.group <- 3
combn(names,people.per.group)

#Output
     [,1]    [,2]    [,3]   [,4]   
[1,] "Alex"  "Alex"  "Alex" "David"
[2,] "David" "David" "John" "John" 
[3,] "John"  "Zoe"   "Zoe"  "Zoe"  

Однако у нас есть проблемы, потому что У Алекса нет хороших отношений с Джоном . Таким образом, мы не хотим включать их обоих в группу . Чтобы мы могли создавать группы для людей, которых мы можем выбрать только одну из них.

# Alex   --> Group 1
# David  --> Group 2
# John   --> Group 1
# Zoe    --> Group 3
only.one.per.group <- c(1,2,1,3)

Я ищу функцию, которая позволяет мне делать то же самое, что и combn, но ограничивает комбинации только переменной.one.per.group. Называя функцию, которую я с нетерпением жду, чтобы использовать var.combn, код будет:

names <- c("Alex","David","John","Zoe")
only.one.per.group <- c(1,2,1,3)
people.per.group <- 3
var.combn(names,people.per.group,only.one.per.group)

#Output
       [,1]     [,2]      
[1,]  "Alex"   "David"
[2,]  "David"  "John" 
[3,]  "Zoe"    "Zoe"  

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

Я надеюсь, что вам понравился пример, и я хотел бы получить какие-либо идеи о том, как это сделать.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Вот довольно компактное решение, основанное на предположении, что должен быть выбран ровно один человек из каждой группы (и это предположение не всегда может быть верным - это было немного неясно из ОП). Он использует тот факт, что должен быть выбран один человек из каждой группы, поэтому, если мы добавим имена к группам и используем expand.grid(), то у нас сразу есть решение.

DF <- data.frame(names=c("Alex","David","John","Zoe"),
                 groups=c(1, 2, 1, 3),
                 stringsAsFactors =FALSE)
expand.grid(lapply(unique(DF$groups), function(i) {DF$names[which(DF$groups==i)]}))

Это производит

  Var1  Var2 Var3
1 Alex David  Zoe
2 John David  Zoe

которые были две комбинации, после которых вы были. Немного более компактное решение (все еще использующее базу R) будет

expand.grid(by(DF, DF$groups, function(x) x$names))

, который, возможно, легче читать.

Он также работает с более сложными группировками:

DF <- data.frame(names=c("Alex","David","John","Zoe", "Bob", "Charles"),
                 groups=c(1, 2, 1, 3, 2, 3),
                 stringsAsFactors =FALSE)

expand.grid(by(DF, DF$groups, function(x) x$names))

, который производит

  Var1  Var2    Var3
1 Alex David     Zoe
2 John David     Zoe
3 Alex   Bob     Zoe
4 John   Bob     Zoe
5 Alex David Charles
6 John David Charles
7 Alex   Bob Charles
8 John   Bob Charles

Теперь, если вы хотите выбрать менее одной единицы из каждой группы, приведенный выше код следует обернуть и применить к результатам, полученным с помощью combn().

0 голосов
/ 08 ноября 2018

Вот другой способ сделать это

Найти все возможные групповые комбинации:

names <- c("Alex","David","John","Zoe")
x <- expand.grid(names, names, names)

Все возможные группы:

    Var1  Var2  Var3
1   Alex  Alex  Alex
2  David  Alex  Alex
3   John  Alex  Alex
4    Zoe  Alex  Alex
5   Alex David  Alex
6  David David  Alex
7   John David  Alex
8    Zoe David  Alex
9   Alex  John  Alex
10 David  John  Alex
11  John  John  Alex
12   Zoe  John  Alex
13  Alex   Zoe  Alex
14 David   Zoe  Alex
15  John   Zoe  Alex
16   Zoe   Zoe  Alex
17  Alex  Alex David
18 David  Alex David
19  John  Alex David
20   Zoe  Alex David
21  Alex David David
22 David David David
23  John David David
24   Zoe David David
25  Alex  John David
26 David  John David
27  John  John David
28   Zoe  John David
29  Alex   Zoe David
30 David   Zoe David
31  John   Zoe David
32   Zoe   Zoe David
33  Alex  Alex  John
34 David  Alex  John
35  John  Alex  John
36   Zoe  Alex  John
37  Alex David  John
38 David David  John
39  John David  John
40   Zoe David  John
41  Alex  John  John
42 David  John  John
43  John  John  John
44   Zoe  John  John
45  Alex   Zoe  John
46 David   Zoe  John
47  John   Zoe  John
48   Zoe   Zoe  John
49  Alex  Alex   Zoe
50 David  Alex   Zoe
51  John  Alex   Zoe
52   Zoe  Alex   Zoe
53  Alex David   Zoe
54 David David   Zoe
55  John David   Zoe
56   Zoe David   Zoe
57  Alex  John   Zoe
58 David  John   Zoe
59  John  John   Zoe
60   Zoe  John   Zoe
61  Alex   Zoe   Zoe
62 David   Zoe   Zoe
63  John   Zoe   Zoe
64   Zoe   Zoe   Zoe

Найти группы, которые удовлетворяют условиям:

 x <- x[which(x[,1] != x[,2]),]
    x <- x[which(x[,1] != x[,3]),]
    x <- x[which(x[,2] != x[,3]),]
    x <- x[-which((x[,1] == "Alex" & x[,2] == "John")),]
    x <- x[-which((x[,1] == "Alex" & x[,3] == "John")),]
    x <- x[-which((x[,2] == "Alex" & x[,3] == "John")),]
    x <- x[-which((x[,2] == "Alex" & x[,1] == "John")),]
    x <- x[-which((x[,3] == "Alex" & x[,1] == "John")),]
    x <- x[-which((x[,3] == "Alex" & x[,2] == "John")),]

Результат:

    Var1  Var2  Var3
8    Zoe David  Alex
14 David   Zoe  Alex
20   Zoe  Alex David
28   Zoe  John David
29  Alex   Zoe David
31  John   Zoe David
40   Zoe David  John
46 David   Zoe  John
50 David  Alex   Zoe
53  Alex David   Zoe
55  John David   Zoe
58 David  John   Zoe
...