我正在尝试在长度为14的向量中生成0和1的所有可能组合。是否有一种简单的方法来将输出作为向量列表或更佳的数据框来获取?
为了更好地展示我在寻找什么,让我们假设我只想要一个长度为3的向量。我希望能够生成以下内容:
(1,1,1), (0,0,0), (1,1,0), (1,0,0), (1,0,1), (0,1,0), (0,1,1), (0,0,0)
您正在寻找expand.grid
。
expand.grid(0:1, 0:1, 0:1)
或者,对于长情况:
n <- 14
l <- rep(list(0:1), n)
expand.grid(l)
作为@Justin方法的替代方法,您还可以使用“ data.table”包中的CJ
。在这里,我还利用replicate
创建了14个零和一的列表。
library(data.table)
do.call(CJ, replicate(14, 0:1, FALSE))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
# 1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# 2: 0 0 0 0 0 0 0 0 0 0 0 0 0 1
# 3: 0 0 0 0 0 0 0 0 0 0 0 0 1 0
# 4: 0 0 0 0 0 0 0 0 0 0 0 0 1 1
# 5: 0 0 0 0 0 0 0 0 0 0 0 1 0 0
# ---
# 16380: 1 1 1 1 1 1 1 1 1 1 1 0 1 1
# 16381: 1 1 1 1 1 1 1 1 1 1 1 1 0 0
# 16382: 1 1 1 1 1 1 1 1 1 1 1 1 0 1
# 16383: 1 1 1 1 1 1 1 1 1 1 1 1 1 0
# 16384: 1 1 1 1 1 1 1 1 1 1 1 1 1 1
有16384个可能的排列。您可以使用iterpc
包来迭代获取结果。
library(iterpc)
I = iterpc(2, 14, label=c(0,1), order=T, replace=T)
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 1
getnext(I)
# [1] 0 0 0 0 0 0 0 0 0 0 0 0 1 0
如果需要所有结果,仍然可以使用getall(I)
。
tidyr
具有与expand.grid()
类似的几个选项。
tidyr::crossing()
返回小标题,并且不会将字符串转换为因数(尽管您可以执行expand.grid(..., stringsAsFactors = F)
)。
library(tidyr)
crossing(var1 = 0:1, var2 = 0:1, var3 = 0:1)
# A tibble: 8 x 3
var1 var2 var3
<int> <int> <int>
1 0 0 0
2 0 0 1
3 0 1 0
4 0 1 1
5 1 0 0
6 1 0 1
7 1 1 0
8 1 1 1
[tidyr::expand()
只能给出出现在数据中的值的两种组合,如下所示:
expand(mtcars, nesting(vs, cyl))
# A tibble: 5 x 2
vs cyl
<dbl> <dbl>
1 0 4
2 0 6
3 0 8
4 1 4
5 1 6
或两个变量的所有可能组合,即使在数据中没有观察到具有这些特定值的观察值,例如:
expand(mtcars, vs, col)
# A tibble: 6 x 2
vs cyl
<dbl> <dbl>
1 0 4
2 0 6
3 0 8
4 1 4
5 1 6
6 1 8
((您会发现原始数据中没有观察到vs == 1&cyl == 8)
tidyr::complete()
也可以类似于expand.grid()
使用。这是来自docs的示例:
df <- dplyr::tibble(
group = c(1:2, 1),
item_id = c(1:2, 2),
item_name = c("a", "b", "b"),
value1 = 1:3,
value2 = 4:6
)
df %>% complete(group, nesting(item_id, item_name))
# A tibble: 4 x 5
group item_id item_name value1 value2
<dbl> <dbl> <chr> <int> <int>
1 1 1 a 1 4
2 1 2 b 3 6
3 2 1 a NA NA
4 2 2 b 2 5
这将为每个组提供item_id和item_name的所有可能的组合-它为第2组的item_id 1和item_name a创建一行。
由于您正在处理0和1,所以用位来考虑整数似乎很自然。使用从此post(以下为MyIntToBit
)稍有更改的功能,以及您选择的apply
功能,我们可以获得所需的结果。
MyIntToBit <- function(x, dig) {
i <- 0L
string <- numeric(dig)
while (x > 0) {
string[dig - i] <- x %% 2L
x <- x %/% 2L
i <- i + 1L
}
string
}
如果要列表,请像这样使用lapply
:
lapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))
如果您喜欢矩阵,则sapply
可以解决问题:
sapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))
下面是示例输出:
> lapply(0:(2^3 - 1), function(x) MyIntToBit(x,3))
[[1]]
[1] 0 0 0
[[2]]
[1] 0 0 1
[[3]]
[1] 0 1 0
[[4]]
[1] 0 1 1
[[5]]
[1] 1 0 0
[[6]]
[1] 1 0 1
[[7]]
[1] 1 1 0
[[8]]
[1] 1 1 1
> sapply(0:(2^3 - 1), function(x) MyIntToBit(x,3))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 0 0 0 0 1 1 1 1
[2,] 0 0 1 1 0 0 1 1
[3,] 0 1 0 1 0 1 0 1
这是以前答案的另一种方法。如果需要将1和0的14个值进行所有可能的组合,则就像生成从0到(2 ^ 14)-1的所有可能的数字并保留它们的二进制表示形式。
n <- 14
lapply(0:(2^n-1), FUN=function(x) head(as.integer(intToBits(x)),n))