来自两个(或多个)向量的所有元素的唯一组合

Unique combination of all elements from two (or more) vectors

提问人:Godel 提问时间:7/9/2012 最后编辑:JaapGodel 更新时间:11/15/2023 访问量:142195

问:

我正在尝试从 R 中两个不同大小的向量创建所有元素的独特组合。

例如,第一个向量是

a <- c("ABC", "DEF", "GHI")

第二个是当前存储为字符串的日期

b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

我需要创建一个包含两列的数据框,如下所示

> data
    a          b
1  ABC 2012-05-01
2  ABC 2012-05-02
3  ABC 2012-05-03
4  ABC 2012-05-04
5  ABC 2012-05-05
6  DEF 2012-05-01
7  DEF 2012-05-02
8  DEF 2012-05-03
9  DEF 2012-05-04
10 DEF 2012-05-05
11 GHI 2012-05-01
12 GHI 2012-05-02
13 GHI 2012-05-03
14 GHI 2012-05-04
15 GHI 2012-05-05

所以基本上,我正在寻找一种独特的组合,方法是将一个向量 (a) 的所有元素与第二个向量 (b) 的所有元素并列。

理想的解决方案是泛化到更多的输入向量。


Смотритетакже:
如何生成组合矩阵

r-faq data.table

评论


答:

177赞 shhhhimhuntingrabbits 7/9/2012 #1

这也许是你所追求的

> expand.grid(a,b)
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

如果生成的顺序不是您想要的,您可以事后排序。如果将参数命名为 ,它们将成为列名:expand.grid

df = expand.grid(a = a, b = b)
df[order(df$a), ]

并泛化到任意数量的输入列。expand.grid

评论

4赞 thelatemail 7/9/2012
而且不需要只做一个排序:plyrresult <- expand.grid(a=a,b=b); result <- result[order(result$a,result$b),];
2赞 Josh 8/27/2019
比我有更多的代表的人能够接受这个答案吗?
0赞 GKi 12/17/2019
如果顺序和名称应如问题所示:expand.grid(b=b,a=a)[2:1]
0赞 Brent 5/14/2020
请注意,标题是 Unique Combinations - 这个答案解决了 OP 问题,但如果 2 列的数据类型相同,并且您应用了 expand.grid,您将拥有唯一的排列,而不是唯一的组合
4赞 izan 6/4/2018 #2

您可以使用 order 函数对任意数量的列进行排序。举个例子

df <- expand.grid(a,b)
> df
   Var1       Var2
1   ABC 2012-05-01
2   DEF 2012-05-01
3   GHI 2012-05-01
4   ABC 2012-05-02
5   DEF 2012-05-02
6   GHI 2012-05-02
7   ABC 2012-05-03
8   DEF 2012-05-03
9   GHI 2012-05-03
10  ABC 2012-05-04
11  DEF 2012-05-04
12  GHI 2012-05-04
13  ABC 2012-05-05
14  DEF 2012-05-05
15  GHI 2012-05-05

> df[order( df[,1], df[,2] ),] 
   Var1       Var2
1   ABC 2012-05-01
4   ABC 2012-05-02
7   ABC 2012-05-03
10  ABC 2012-05-04
13  ABC 2012-05-05
2   DEF 2012-05-01
5   DEF 2012-05-02
8   DEF 2012-05-03
11  DEF 2012-05-04
14  DEF 2012-05-05
3   GHI 2012-05-01
6   GHI 2012-05-02
9   GHI 2012-05-03
12  GHI 2012-05-04
15  GHI 2012-05-05`
53赞 hypothesis 6/21/2018 #3

该软件包提供了不错的替代方案,它比经典函数效果更好,因为 (1) 字符串不会转换为因子,并且 (2) 排序更直观:tidyrcrossingexpand.grid

library(tidyr)

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

crossing(a, b)

# A tibble: 15 x 2
       a          b
   <chr>      <chr>
 1   ABC 2012-05-01
 2   ABC 2012-05-02
 3   ABC 2012-05-03
 4   ABC 2012-05-04
 5   ABC 2012-05-05
 6   DEF 2012-05-01
 7   DEF 2012-05-02
 8   DEF 2012-05-03
 9   DEF 2012-05-04
10   DEF 2012-05-05
11   GHI 2012-05-01
12   GHI 2012-05-02
13   GHI 2012-05-03
14   GHI 2012-05-04
15   GHI 2012-05-05

评论

0赞 Jojanzing 11/10/2022
expand.grid有一个可以设置为 的参数,用于求解 (1)。stringsAsFactorsFALSE
27赞 Jaap 1/29/2019 #4

概述中缺少 中的 -function。用:CJ

library(data.table)
CJ(a, b, unique = TRUE)

给:

      a          b
 1: ABC 2012-05-01
 2: ABC 2012-05-02
 3: ABC 2012-05-03
 4: ABC 2012-05-04
 5: ABC 2012-05-05
 6: DEF 2012-05-01
 7: DEF 2012-05-02
 8: DEF 2012-05-03
 9: DEF 2012-05-04
10: DEF 2012-05-05
11: GHI 2012-05-01
12: GHI 2012-05-02
13: GHI 2012-05-03
14: GHI 2012-05-04
15: GHI 2012-05-05

注意:从版本 1.12.2 开始,CJ 会自动命名生成的列(另请参阅此处和此处)。

10赞 tmfmnk 9/17/2019 #5

从 1.0.0 版开始,提供了自己的 .它通过一个处理向量的低级函数完成了现有的 expand()、nesting() 和 crossing() 系列tidyrexpand.grid()

与以下产品相比:base::expand.grid()

最快地改变第一个元素。从不将字符串转换为因子。 不添加任何其他属性。返回 tibble,而不是数据 框架。可以扩展任何广义向量,包括数据框。

a <- c("ABC", "DEF", "GHI")
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

tidyr::expand_grid(a, b)

   a     b         
   <chr> <chr>     
 1 ABC   2012-05-01
 2 ABC   2012-05-02
 3 ABC   2012-05-03
 4 ABC   2012-05-04
 5 ABC   2012-05-05
 6 DEF   2012-05-01
 7 DEF   2012-05-02
 8 DEF   2012-05-03
 9 DEF   2012-05-04
10 DEF   2012-05-05
11 GHI   2012-05-01
12 GHI   2012-05-02
13 GHI   2012-05-03
14 GHI   2012-05-04
15 GHI   2012-05-05
1赞 clp 11/30/2022 #6

在基础 R 中,您可以尝试 merge()、cbind() 和 expand.grid()。

a <- seq(1E4)
b <- c("2012-05-01", "2012-05-02", "2012-05-03", "2012-05-04", "2012-05-05")

 microbenchmark(
  "merge (1)" = mmm <- as.matrix(merge(a, b)),
  "diy (2)"   = {ccc <- cbind( rep(a, length(b)),
                               b[rep(seq_along(b), each = length(a))]
                        )
                },
 "diy R (3)"  = {ccc <- cbind( a,
                               b[rep(seq_along(b), each = length(a))]
                        )
                },
  "grid (4)"  = ggg <- expand.grid(a, b),
  times       = 2
)

输出。

Unit: milliseconds
      expr      min       lq     mean   median       uq      max neval
 merge (1) 863.3100 863.3100 888.6573 888.6573 914.0046 914.0046     2
   diy (2) 117.1912 117.1912 142.1394 142.1394 167.0875 167.0875     2
 diy R (3)  34.9320  34.9320  49.4119  49.4119  63.8918  63.8918     2
  grid (4)  45.1876  45.1876  46.1592  46.1592  47.1308  47.1308     2
1赞 LMc 4/25/2023 #7

可以使用基本 R 数据帧回收的事实:rep

data.frame(a = rep(a, each = length(b)), b = b)