提问人:Godel 提问时间:7/9/2012 最后编辑:JaapGodel 更新时间:11/15/2023 访问量:142195
来自两个(或多个)向量的所有元素的唯一组合
Unique combination of all elements from two (or more) vectors
问:
我正在尝试从 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) 的所有元素并列。
理想的解决方案是泛化到更多的输入向量。
Смотритетакже:
如何生成组合矩阵
答:
这也许是你所追求的
> 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
评论
plyr
result <- expand.grid(a=a,b=b); result <- result[order(result$a,result$b),];
expand.grid(b=b,a=a)[2:1]
您可以使用 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`
该软件包提供了不错的替代方案,它比经典函数效果更好,因为 (1) 字符串不会转换为因子,并且 (2) 排序更直观:tidyr
crossing
expand.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
评论
expand.grid
有一个可以设置为 的参数,用于求解 (1)。stringsAsFactors
FALSE
此 r-faq 概述中缺少 data.table-package 中的 -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
会自动命名生成的列(另请参阅此处和此处)。
从 1.0.0 版开始,提供了自己的 .它通过一个处理向量的低级函数完成了现有的 expand()、
nesting(
) 和 crossing()
系列。tidyr
expand.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
在基础 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
可以使用基本 R 数据帧回收的事实:rep
data.frame(a = rep(a, each = length(b)), b = b)
评论