R 中的替换和规则排列
Permutations with replacement and rules in R
我需要做一种 Truth table 与 Monte Carlo 模拟一起使用。
基本上我需要用 110 个“操作数”为 0 和 1 生成排列,但有一些规则。
例如:它不能有两个并排的零
使用 3 列的示例(我需要 110)
c_1 c_2 c_3
0 0 0 = DROP
0 0 1 = DROP
0 1 0 = OK
0 1 1 = OK
1 0 0 = DROP
1 0 1 = OK
1 1 0 = OK
1 1 1 = OK
我正在尝试使用包裹安排,但我不知道如何应用这些规则。
创建测试数据,g
,然后将列粘贴在一起并使用 grep
查找没有双零的行。然后索引g
。
g <- expand.grid(c_1 = 0:1, c_2 = 0:1, c_3 = 0:1) # test data
ok <- ! grepl("00", do.call("paste0", g))
g[ok, ]
给予:
c_1 c_2 c_3
3 0 1 0
4 1 1 0
6 1 0 1
7 0 1 1
8 1 1 1
一行
如果你有一个单独的行作为向量然后使用as.list
来使用上面的:
x <- c(0, 1, 1)
! grepl("00", do.call("paste0", as.list(x)))
## [1] TRUE
枚举
如果有 n 列,则任何行中的零都不能超过 ceiling(n/2) 个,因此为了枚举所有可能性,我们可以用一个零枚举所有行,然后是两个零,...,ceiling (n/2) 个零。使用 k zeros 的 arrangements 包 NotDoubleZero 初始化一个结构并 iter 迭代它直到没有更多的点它 returns NULL
library(arrangements)
NotDoubleZero <- function(n, k = 0) {
structure(NA, icomb = icombinations(n, k))
}
iter <- function(x, ...) {
if (is.null(x)) return(NULL)
icomb <- attr(x, "icomb")
n <- icomb$n
k <- icomb$k
repeat {
r <- icomb$getnext()
if (is.null(r) || all(diff(r) > 1)) break
}
if (is.null(r)) {
k <- k + 1
if (k > ceiling(n/2)) return(NULL)
x <- NotDoubleZero(n, k)
iter(x)
} else structure(r, icomb = icomb)
}
# test
res <- NotDoubleZero(3)
while(!is.null(res <- iter(res))) cat("Positions of 0's: <", res, "> \n")
给予:
Positions of 0's: < > <- no zeros, i.e. all ones
Positions of 0's: < 1 >
Positions of 0's: < 2 >
Positions of 0's: < 3 >
Positions of 0's: < 1 3 >
给定 k 的随机行
给定 n(列数)和 k(零数),给出随机行中零的位置。您也可以随机生成 k 但这不会在行上提供均匀分布;但是,也许这就足够了。
set.seed(123)
n <- 3
k <- 2
repeat {
r <- sort(sample(n, k))
if (all(diff(r) > 1)) break
}
r
## [1] 1 3
1 - replace(numeric(n), r, 1)
## [1] 0 1 0
我需要做一种 Truth table 与 Monte Carlo 模拟一起使用。
基本上我需要用 110 个“操作数”为 0 和 1 生成排列,但有一些规则。
例如:它不能有两个并排的零
使用 3 列的示例(我需要 110)
c_1 c_2 c_3
0 0 0 = DROP
0 0 1 = DROP
0 1 0 = OK
0 1 1 = OK
1 0 0 = DROP
1 0 1 = OK
1 1 0 = OK
1 1 1 = OK
我正在尝试使用包裹安排,但我不知道如何应用这些规则。
创建测试数据,g
,然后将列粘贴在一起并使用 grep
查找没有双零的行。然后索引g
。
g <- expand.grid(c_1 = 0:1, c_2 = 0:1, c_3 = 0:1) # test data
ok <- ! grepl("00", do.call("paste0", g))
g[ok, ]
给予:
c_1 c_2 c_3
3 0 1 0
4 1 1 0
6 1 0 1
7 0 1 1
8 1 1 1
一行
如果你有一个单独的行作为向量然后使用as.list
来使用上面的:
x <- c(0, 1, 1)
! grepl("00", do.call("paste0", as.list(x)))
## [1] TRUE
枚举
如果有 n 列,则任何行中的零都不能超过 ceiling(n/2) 个,因此为了枚举所有可能性,我们可以用一个零枚举所有行,然后是两个零,...,ceiling (n/2) 个零。使用 k zeros 的 arrangements 包 NotDoubleZero 初始化一个结构并 iter 迭代它直到没有更多的点它 returns NULL
library(arrangements)
NotDoubleZero <- function(n, k = 0) {
structure(NA, icomb = icombinations(n, k))
}
iter <- function(x, ...) {
if (is.null(x)) return(NULL)
icomb <- attr(x, "icomb")
n <- icomb$n
k <- icomb$k
repeat {
r <- icomb$getnext()
if (is.null(r) || all(diff(r) > 1)) break
}
if (is.null(r)) {
k <- k + 1
if (k > ceiling(n/2)) return(NULL)
x <- NotDoubleZero(n, k)
iter(x)
} else structure(r, icomb = icomb)
}
# test
res <- NotDoubleZero(3)
while(!is.null(res <- iter(res))) cat("Positions of 0's: <", res, "> \n")
给予:
Positions of 0's: < > <- no zeros, i.e. all ones
Positions of 0's: < 1 >
Positions of 0's: < 2 >
Positions of 0's: < 3 >
Positions of 0's: < 1 3 >
给定 k 的随机行
给定 n(列数)和 k(零数),给出随机行中零的位置。您也可以随机生成 k 但这不会在行上提供均匀分布;但是,也许这就足够了。
set.seed(123)
n <- 3
k <- 2
repeat {
r <- sort(sample(n, k))
if (all(diff(r) > 1)) break
}
r
## [1] 1 3
1 - replace(numeric(n), r, 1)
## [1] 0 1 0