R中的条件采样
conditionally sample in R
我在另一个 post 中发现了 ,它在调用时按顺序输出向量组合。当有大量包含许多元素的向量时,它本质上是 expand.grid
的一种变通方法。
函数如下:
lazyExpandGrid <- function(...) {
dots <- list(...)
argnames <- names(dots)
if (is.null(argnames)) argnames <- paste0('Var', seq_along(dots))
sizes <- lengths(dots)
indices <- cumprod(c(1L, sizes))
maxcount <- indices[ length(indices) ]
i <- 0
function(index) {
i <<- if (missing(index)) (i + 1L) else index
if (length(i) > 1L) return(do.call(rbind.data.frame, lapply(i, sys.function(0))))
if (i > maxcount || i < 1L) return(FALSE)
setNames(Map(`[[`, dots, (i - 1L) %% indices[-1L] %/% indices[-length(indices)] + 1L ),
argnames)
}
}
以下是一些调用示例:
set.seed(42)
nxt <- lazyExpandGrid(a=1:1e2, b=1:1e2, c=1:1e2, d=1:1e2, e=1:1e2, f=1:1e2)
as.data.frame(nxt()) # prints the 1st possible combination
nxt(sample(1e2^6, size=7)) # prints 7 sampled rows from the sample space
我想不通的是如何使用 lazyExpandGrid2
进行条件采样。如果样本具有一定数量的元素,我想排除样本。
例如,假设我有这些向量,我想为其创建独特的组合:a=0:3, b=0:4, c=0:5
。我可以使用以下方法创建样本:nxt(sample(50, size=50, replace = F))
。
但是可以说我对有两个 0 的样本不感兴趣。我怎样才能排除这些样本?我试过类似的东西:nxt(sample(which(!(sum(as.data.frame(nxt()) == 0)==2)), size=50, replace = F))
。
我只是不明白如何引用 sample()
中的抽样行,以便能够在它不符合特定条件时将其排除。
如果你想删除不符合条件的行,我认为你不需要担心没有替换的采样,因为将相同的值传递给nxt
应该会生成相同的行,这仍然会被丢弃。那么,它可能会像您在上面定义的那样为函数制作一个包装器,如果它不满足您所追求的条件,它就不会包含 nxt
生成的行。这里,如果零的数量等于 2,则删除该行:
set.seed(0123)
nxt <- lazyExpandGrid(a = 0:3, b = 0:4, c = 0:5)
nxtDrop <- function(samp, n_row){
t(sapply(1:n_row, function(x) {
y = nxt(sample(samp, 1))
while (length(grep(0, y)) == 2) {
y = nxt(sample(samp, 1))
}
return(y)
}))
}
> nxtDrop(120, 10)
a b c
[1,] 2 3 1
[2,] 2 3 4
[3,] 1 2 2
[4,] 1 1 5
[5,] 0 3 5
[6,] 1 1 0
[7,] 3 0 3
[8,] 3 1 5
[9,] 2 1 3
[10,] 2 3 2
我在另一个 post 中发现了 expand.grid
的一种变通方法。
函数如下:
lazyExpandGrid <- function(...) {
dots <- list(...)
argnames <- names(dots)
if (is.null(argnames)) argnames <- paste0('Var', seq_along(dots))
sizes <- lengths(dots)
indices <- cumprod(c(1L, sizes))
maxcount <- indices[ length(indices) ]
i <- 0
function(index) {
i <<- if (missing(index)) (i + 1L) else index
if (length(i) > 1L) return(do.call(rbind.data.frame, lapply(i, sys.function(0))))
if (i > maxcount || i < 1L) return(FALSE)
setNames(Map(`[[`, dots, (i - 1L) %% indices[-1L] %/% indices[-length(indices)] + 1L ),
argnames)
}
}
以下是一些调用示例:
set.seed(42)
nxt <- lazyExpandGrid(a=1:1e2, b=1:1e2, c=1:1e2, d=1:1e2, e=1:1e2, f=1:1e2)
as.data.frame(nxt()) # prints the 1st possible combination
nxt(sample(1e2^6, size=7)) # prints 7 sampled rows from the sample space
我想不通的是如何使用 lazyExpandGrid2
进行条件采样。如果样本具有一定数量的元素,我想排除样本。
例如,假设我有这些向量,我想为其创建独特的组合:a=0:3, b=0:4, c=0:5
。我可以使用以下方法创建样本:nxt(sample(50, size=50, replace = F))
。
但是可以说我对有两个 0 的样本不感兴趣。我怎样才能排除这些样本?我试过类似的东西:nxt(sample(which(!(sum(as.data.frame(nxt()) == 0)==2)), size=50, replace = F))
。
我只是不明白如何引用 sample()
中的抽样行,以便能够在它不符合特定条件时将其排除。
如果你想删除不符合条件的行,我认为你不需要担心没有替换的采样,因为将相同的值传递给nxt
应该会生成相同的行,这仍然会被丢弃。那么,它可能会像您在上面定义的那样为函数制作一个包装器,如果它不满足您所追求的条件,它就不会包含 nxt
生成的行。这里,如果零的数量等于 2,则删除该行:
set.seed(0123)
nxt <- lazyExpandGrid(a = 0:3, b = 0:4, c = 0:5)
nxtDrop <- function(samp, n_row){
t(sapply(1:n_row, function(x) {
y = nxt(sample(samp, 1))
while (length(grep(0, y)) == 2) {
y = nxt(sample(samp, 1))
}
return(y)
}))
}
> nxtDrop(120, 10)
a b c
[1,] 2 3 1
[2,] 2 3 4
[3,] 1 2 2
[4,] 1 1 5
[5,] 0 3 5
[6,] 1 1 0
[7,] 3 0 3
[8,] 3 1 5
[9,] 2 1 3
[10,] 2 3 2