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

我试图创建一个独特的组合的所有元素从两个矢量的不同大小在 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)的所有元素并列来寻找一个唯一的组合。

一个理想的解决方案将推广到更多的输入向量。


参见:
如何生成组合矩阵

127666 次浏览

也许这就是你想要的

> 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泛化为任意数量的输入列。

您可以使用顺序函数对任意数量的列进行排序

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`

tidyr包提供了很好的替代 crossing,它比经典的 expand.grid函数工作得更好,因为(1)字符串不会转换成因子(2)排序更直观:

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

在这个 概述中缺少的是 包中的 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对生成的列进行了自动命名(也请参见 给你给你)。

从版本1.0.0开始,tidyr提供了自己的版本 expand.grid()

base::expand.grid()相比:

更改第一个元素的速度最快。永远不要将字符串转换为因数。 不添加任何其他属性。返回一个字符串,而不是数据 可以扩展任何广义向量,包括数据帧。

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

在基础 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