生成向量元素的所有可能组合的列表

May*_*you 43 combinations r

我试图在长度为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)
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激!

谢谢,

Jus*_*tin 77

你在找expand.grid.

expand.grid(0:1, 0:1, 0:1)
Run Code Online (Sandbox Code Playgroud)

或者,长期来看:

n <- 14
l <- rep(list(0:1), n)

expand.grid(l)
Run Code Online (Sandbox Code Playgroud)


A5C*_*2T1 6

作为@ Justin方法的替代方法,您也可以使用CJ"data.table"包.在这里,我还使用了replicate创建14个零和1的列表.

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
Run Code Online (Sandbox Code Playgroud)


use*_*745 6

这里有一个美丽的最小可复制示例:

x <- c("red", "blue", "black")
do.call(c, lapply(seq_along(x), combn, x = x, simplify = FALSE))
# [[1]]
# [1] "red"
# 
# [[2]]
# [1] "blue"
# 
# [[3]]
# [1] "black"
# 
# [[4]]
# [1] "red"  "blue"
# 
# [[5]]
# [1] "red"   "black"
# 
# [[6]]
# [1] "blue"  "black"
# 
# [[7]]
# [1] "red"   "blue"  "black"
Run Code Online (Sandbox Code Playgroud)

所有功劳都归功于@RichScriven


Ran*_*Lai 5

有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
Run Code Online (Sandbox Code Playgroud)

如果您想要所有结果,您仍然可以使用getall(I).


Jos*_*ood 5

由于您正在处理 0 和 1,因此以位来考虑整数似乎是很自然的。使用本文中稍作修改的函数(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
}
Run Code Online (Sandbox Code Playgroud)

如果你想要一个列表,请lapply像这样使用:

lapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))
Run Code Online (Sandbox Code Playgroud)

如果你更喜欢矩阵,sapply可以这样做:

sapply(0:(2^14 - 1), function(x) MyIntToBit(x,14))
Run Code Online (Sandbox Code Playgroud)

以下是示例输出:

> 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 
Run Code Online (Sandbox Code Playgroud)


sbh*_*bha 5

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

或两个变量的所有可能组合,即使没有观察到数据中数据的特定值,例如:

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
Run Code Online (Sandbox Code Playgroud)

(您会发现原始数据中没有观察到vs == 1&cyl == 8)

tidyr::complete()也可以类似于expand.grid()。这是来自文档的示例:

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
Run Code Online (Sandbox Code Playgroud)

这将为每个组提供item_id和item_name的所有可能组合-它为第2组item_id 1和item_name a创建一行。


eng*_*uze 5

我在这里讨论了一种解决所有类似问题的通用方法。首先让我们看看解决方案如何随着 N 数量的增加而演变,以找出一般模式。

首先,长度为 1 的解是

0
1
Run Code Online (Sandbox Code Playgroud)

现在对于长度 2,解决方案变为(第二列由 | 分隔):

0 | 0 0, 0 1
1 | 1 0, 1 1
Run Code Online (Sandbox Code Playgroud)

将其与长度为 1 的先前解决方案进行比较,很明显,为了获得这个新解决方案,我们只需将 0 和 1 附加到先前的每个解决方案(第一列,0 和 1)。

现在对于长度 3,解决方案是(第 3 列):

0 | 0 0 | 0 0 0, 0 0 1
1 | 1 0 | 1 0 0, 1 0 1
  | 0 1 | 0 1 0, 0 1 1
  | 1 1 | 1 1 0, 1 1 1
Run Code Online (Sandbox Code Playgroud)

同样,这个新的解决方案是通过将 0 和 1 附加到每个先前的解决方案(长度为 2 的第二列)来获得的。

这种观察自然会导致递归解决方案。假设我们已经获得了长度 N-1 的solution(c(0,1), N-1)解,为了获得 N 的解,我们只需将 0 和 1 附加到解 N-1 的每一项append_each_to_list(solution(c(0,1), N-1), c(0,1))。请注意这里更复杂的问题(解决 N)如何自然地分解为更简单的问题(解决 N-1)。

然后我们只需要将这个简单的英语翻译成几乎字面意思的 R 代码:

# assume you have got solution for a shorter length len-1 -> solution(v, len-1) 
# the solution of length len will be the solution of shorter length appended with each element in v 
solution <- function(v, len) {
  if (len<=1) {
    as.list(v)
  } else {
    append_each_to_list(solution(v, len-1), v)
  } 
}

# function to append each element in vector v to list L and return a list
append_each_to_list <- function(L, v) {
  purrr::flatten(lapply(v, 
         function(n) lapply(L, function(l) c(l, n))
         ))
}
Run Code Online (Sandbox Code Playgroud)

调用函数:

> solution(c(1,0), 3)
[[1]]
[1] 1 1 1

[[2]]
[1] 0 1 1

[[3]]
[1] 1 0 1

[[4]]
[1] 0 0 1

[[5]]
[1] 1 1 0

[[6]]
[1] 0 1 0

[[7]]
[1] 1 0 0
Run Code Online (Sandbox Code Playgroud)