如何从多个向量创建唯一的组合列表?

时间:2019-01-17 18:11:30

标签: r

我想确定总共可以使用2种不同的配料在不同的面包上订购多少种比萨饼。但是我想创建一个唯一组合的列表。

我已经使用了rangings包中的combinations()函数来创建唯一组合的列表,并且我将其用于浇头。我正在努力弄清楚如何掺入地壳。

toppings <- c("Pepperoni", "Canadian Bacon", "Sausage", "Italian Sausage")
crust <- c("Thick", "Thin", "Cracker")
toppingcombo <- combinations(toppings)
pizza <- arrangements::combinations(c(crust, toppings), 3)

最后一行代码将其显示为结果。

     [,1]    [,2]            
[1,] "Thick" "Thin"          
[2,] "Thick" "Tuscano"       
[3,] "Thick" "Pepperoni" 

我希望结果显示出来

     [,1]    [,2]        [,3]            
[1,] "Thick" "Sausage"   "Bacon"         
[2,] "Thick" "Pepperoni" "Sausage       

但是请避免创建重复项,例如“厚/培根/香肠”,因为这与第[1,]行相同,但浇头的顺序不同。

4 个答案:

答案 0 :(得分:4)

我对您的输入数据进行了一些修改,以实现您想要的目标。

数据

toppings <- c("Pepperoni", "Canadian Bacon", "Sausage", "Italian Sausage")
crust <- data.frame(crust = c("Thick", "Thin", "Cracker"))

library(arrangements)
topping_combo <- as.data.frame(combinations(toppings, k = 2, n = length(toppings)))
colnames(topping_combo) <- c("topping_1", "topping_2")

因此,现在我们有两个数据帧:crust只有一列三行,每种地壳一个; topping_combo是一个6x2数据帧,其中包含所有可能的浇头的2种组合。

代码

以下代码提供了一种可能的解决方案,以创建一个数据框,其中每一行都是您所要求的比萨饼类型。我们使用crossing包中的函数tidyr

library(tidyr)
crossing(crust, topping_combo)

输出

     crust      topping_1       topping_2
1    Thick      Pepperoni  Canadian Bacon
2    Thick      Pepperoni         Sausage
3    Thick      Pepperoni Italian Sausage
4    Thick Canadian Bacon         Sausage
5    Thick Canadian Bacon Italian Sausage
6    Thick        Sausage Italian Sausage
7     Thin      Pepperoni  Canadian Bacon
8     Thin      Pepperoni         Sausage
9     Thin      Pepperoni Italian Sausage
10    Thin Canadian Bacon         Sausage
11    Thin Canadian Bacon Italian Sausage
12    Thin        Sausage Italian Sausage
13 Cracker      Pepperoni  Canadian Bacon
14 Cracker      Pepperoni         Sausage
15 Cracker      Pepperoni Italian Sausage
16 Cracker Canadian Bacon         Sausage
17 Cracker Canadian Bacon Italian Sausage
18 Cracker        Sausage Italian Sausage

答案 1 :(得分:3)

使用基数R,类似于@RicS的答案,您可以使用expand.gridcbind分两步制作一个顶部连击表并将其与外壳交叉连接:

top_combo = t(combn(toppings, 2))
eg = expand.grid(crust = crust, tc = seq_len(nrow(top_combo)))
res = cbind(eg, top_combo[eg$tc, ])

     crust tc              1               2
1    Thick  1      Pepperoni  Canadian Bacon
2     Thin  1      Pepperoni  Canadian Bacon
3  Cracker  1      Pepperoni  Canadian Bacon
4    Thick  2      Pepperoni         Sausage
5     Thin  2      Pepperoni         Sausage
6  Cracker  2      Pepperoni         Sausage
7    Thick  3      Pepperoni Italian Sausage
8     Thin  3      Pepperoni Italian Sausage
9  Cracker  3      Pepperoni Italian Sausage
10   Thick  4 Canadian Bacon         Sausage
11    Thin  4 Canadian Bacon         Sausage
12 Cracker  4 Canadian Bacon         Sausage
13   Thick  5 Canadian Bacon Italian Sausage
14    Thin  5 Canadian Bacon Italian Sausage
15 Cracker  5 Canadian Bacon Italian Sausage
16   Thick  6        Sausage Italian Sausage
17    Thin  6        Sausage Italian Sausage
18 Cracker  6        Sausage Italian Sausage

答案 2 :(得分:2)

考虑通过将两个向量都传递到sapply中来构建矩阵列表,然后在行末绑定所有元素:

pizza_list <- sapply(crust, function(x,y) cbind(x, t(combn(y, m=2))), toppings, simplify=FALSE)

pizza <- do.call(rbind, pizza_list)
colnames(pizza) <- c("Crust", "Toppings1", "Toppings2")

pizza    
#       Crust     Toppings1        Toppings2        
#  [1,] "Thick"   "Pepperoni"      "Canadian Bacon" 
#  [2,] "Thick"   "Pepperoni"      "Sausage"        
#  [3,] "Thick"   "Pepperoni"      "Italian Sausage"
#  [4,] "Thick"   "Canadian Bacon" "Sausage"        
#  [5,] "Thick"   "Canadian Bacon" "Italian Sausage"
#  [6,] "Thick"   "Sausage"        "Italian Sausage"
#  [7,] "Thin"    "Pepperoni"      "Canadian Bacon" 
#  [8,] "Thin"    "Pepperoni"      "Sausage"        
#  [9,] "Thin"    "Pepperoni"      "Italian Sausage"
# [10,] "Thin"    "Canadian Bacon" "Sausage"        
# [11,] "Thin"    "Canadian Bacon" "Italian Sausage"
# [12,] "Thin"    "Sausage"        "Italian Sausage"
# [13,] "Cracker" "Pepperoni"      "Canadian Bacon" 
# [14,] "Cracker" "Pepperoni"      "Sausage"        
# [15,] "Cracker" "Pepperoni"      "Italian Sausage"
# [16,] "Cracker" "Canadian Bacon" "Sausage"        
# [17,] "Cracker" "Canadian Bacon" "Italian Sausage"
# [18,] "Cracker" "Sausage"        "Italian Sausage"

here

答案 3 :(得分:0)

以下使用dplyr通过crusttoppingsexpand之间创建所有组合。然后将toppings按字母顺序排序(topping_1 <topping_2)并提取unique集。

> library(tidyverse)
> df <- data.frame(
  toppings = c(
    'Pepperoni',
    'Canadian Bacon',
    'Sausage',
    'Italian Sausage'
  ),
  crust = c(
    'Thick', 
    'Thin',
    'Cracker',
    NA # to match the number of toppings
  ),
  stringsAsFactors = FALSE
)

> pizza <- df %>% expand(
  crust,
  toppings,
  toppings
) %>% transmute(
  crust = crust,
  topping_1 = if_else(
    toppings < toppings1,
    toppings,
    toppings1
  ),
  topping_2 = if_else(
    toppings < toppings1,
    toppings1,
    toppings
  )
) %>% filter(
  !is.na(crust), # Remove no-base pizzas
  topping_1 != topping_2 # Remove double-toppings of the same kind
) %>% unique() # Keep only unique combinations across crust, topping_1 and topping_2

> pizza
# A tibble: 18 x 3
   crust   topping_1       topping_2      
   <chr>   <chr>           <chr>          
 1 Cracker Canadian Bacon  Italian Sausage
 2 Cracker Canadian Bacon  Pepperoni      
 3 Cracker Canadian Bacon  Sausage        
 4 Cracker Italian Sausage Pepperoni      
 5 Cracker Italian Sausage Sausage        
 6 Cracker Pepperoni       Sausage        
 7 Thick   Canadian Bacon  Italian Sausage
 8 Thick   Canadian Bacon  Pepperoni      
 9 Thick   Canadian Bacon  Sausage        
10 Thick   Italian Sausage Pepperoni      
11 Thick   Italian Sausage Sausage        
12 Thick   Pepperoni       Sausage        
13 Thin    Canadian Bacon  Italian Sausage
14 Thin    Canadian Bacon  Pepperoni      
15 Thin    Canadian Bacon  Sausage        
16 Thin    Italian Sausage Pepperoni      
17 Thin    Italian Sausage Sausage        
18 Thin    Pepperoni       Sausage